diff --git a/packages/core/src/Serialization/Update/ProtocolParamUpdate.ts b/packages/core/src/Serialization/Update/ProtocolParamUpdate.ts index f352cb13421..4f3b39eedb0 100644 --- a/packages/core/src/Serialization/Update/ProtocolParamUpdate.ts +++ b/packages/core/src/Serialization/Update/ProtocolParamUpdate.ts @@ -162,10 +162,16 @@ export class ProtocolParamUpdate { } if (this.#extraEntropy) { - writer.writeInt(13n); - writer.writeStartArray(2); - writer.writeInt(1); - writer.writeByteString(Buffer.from(this.#extraEntropy, 'hex')); + if (this.#extraEntropy.length === 0) { + writer.writeInt(13n); + writer.writeStartArray(1); + writer.writeInt(0); + } else { + writer.writeInt(13n); + writer.writeStartArray(2); + writer.writeInt(1); + writer.writeByteString(Buffer.from(this.#extraEntropy, 'hex')); + } } if (this.#protocolVersion) { @@ -322,11 +328,16 @@ export class ProtocolParamUpdate { params.#d = UnitInterval.fromCbor(HexBlob.fromBytes(reader.readEncodedValue())); break; case 13n: - // entropy is encoded as an array of two elements, where the second elements is the entropy value - reader.readStartArray(); - reader.readEncodedValue(); - params.#extraEntropy = HexBlob.fromBytes(reader.readByteString()); - reader.readEndArray(); + if (reader.readStartArray() === 1) { + reader.readEncodedValue(); + // Entropy was set as empty + params.#extraEntropy = '' as HexBlob; + reader.readEndArray(); + } else { + reader.readEncodedValue(); + params.#extraEntropy = HexBlob.fromBytes(reader.readByteString()); + reader.readEndArray(); + } break; case 14n: params.#protocolVersion = ProtocolVersion.fromCbor(HexBlob.fromBytes(reader.readEncodedValue())); diff --git a/packages/core/test/Serialization/Transaction.test.ts b/packages/core/test/Serialization/Transaction.test.ts index c31026cb666..41360ac32e7 100644 --- a/packages/core/test/Serialization/Transaction.test.ts +++ b/packages/core/test/Serialization/Transaction.test.ts @@ -1,3 +1,4 @@ +import * as Crypto from '@cardano-sdk/crypto'; import { Transaction, TransactionBody, TxCBOR } from '../../src/Serialization'; import { babbageTx, tx as coreTx, signature, vkey } from './testData'; @@ -10,6 +11,10 @@ const TX2 = const CLI_TX = '84a40081825820f6dd880fb30480aa43117c73bfd09442ba30de5644c3ec1a91d9232fbe715aab000182a20058390071213dc119131f48f54d62e339053388d9d84faedecba9d8722ad2cad9debf34071615fc6452dfc743a4963f6bec68e488001c7384942c13011b0000000253c8e4f6a300581d702ed2631dbb277c84334453c5c437b86325d371f0835a28b910a91a6e011a001e848002820058209d7fee57d1dbb9b000b2a133256af0f2c83ffe638df523b2d1c13d405356d8ae021a0002fb050b582088e4779d217d10398a705530f9fb2af53ffac20aef6e75e85c26e93a00877556a10481d8799fd8799f40ffd8799fa1d8799fd8799fd87980d8799fd8799f581c71213dc119131f48f54d62e339053388d9d84faedecba9d8722ad2caffd8799fd8799fd8799f581cd9debf34071615fc6452dfc743a4963f6bec68e488001c7384942c13ffffffffffd8799f4040ffff1a001e8480a0a000ffd87c9f9fd8799fd8799fd8799fd87980d8799fd8799f581caa47de0ab3b7f0b1d8d196406b6af1b0d88cd46168c49ca0557b4f70ffd8799fd8799fd8799f581cd4b8fc88aec1d1c2f43ca5587898d88da20ef73964b8cf6f8f08ddfbffffffffffd8799fd87980d8799fd8799f581caa47de0ab3b7f0b1d8d196406b6af1b0d88cd46168c49ca0557b4f70ffd8799fd8799fd8799f581cd4b8fc88aec1d1c2f43ca5587898d88da20ef73964b8cf6f8f08ddfbffffffffffd8799f4040ffd87a9f1a00989680ffffd87c9f9fd8799fd87a9fd8799f4752656c65617365d8799fd87980d8799fd8799f581caa47de0ab3b7f0b1d8d196406b6af1b0d88cd46168c49ca0557b4f70ffd8799fd8799fd8799f581cd4b8fc88aec1d1c2f43ca5587898d88da20ef73964b8cf6f8f08ddfbffffffffffff9fd8799f0101ffffffd87c9f9fd8799fd87b9fd9050280ffd87980ffff1b000001884e1fb1c0d87980ffffff1b000001884e1fb1c0d87980ffffff1b000001884e1fb1c0d87980fffff5f6'; +// See https://cardanoscan.io/transaction/fc863a441b55acceebb7d25c81ff7259e4fc9b92fbdf6d594118fb8f1110a78c +const TX_SET_ENTROPY_TO_EMPTY = + '83a50081825820bf30608a974d09c56dd62ca10199ec11746ea2d90dbd83649d4f37c629b1ba840001818258390117d237fb8f952c995cd28f73c555adc2307322d819b7f565196ce754348144bff68f23c1386b85dea0f8425ca574b1a11e188ffaba67537c1a0048f96f021a000351d1031a019732f30682a7581c162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82a10d8100581c2075a095b3c844a29c24317a94a643ab8e22d54a3a3a72a420260af6a10d8100581c268cfc0b89e910ead22e0ade91493d8212f53f3e2164b2e4bef0819ba10d8100581c60baee25cbc90047e83fd01e1e57dc0b06d3d0cb150d0ab40bbfead1a10d8100581cad5463153dc3d24b9ff133e46136028bdc1edbb897f5a7cf1b37950ca10d8100581cb9547b8a57656539a8d9bc42c008e38d9c8bd9c8adbb1e73ad529497a10d8100581cf7b341c14cd58fca4195a9b278cce1ef402dc0e06deb77e543cd1757a10d8100190103a1008882582061261a95b7613ee6bf2067dad77b70349729b0c50d57bc1cf30de0db4a1e73a858407d72721e7504e12d50204f7d9e9d9fe60d9c6a4fd18ad629604729df4f7f3867199b62885623fab68a02863e7877955ca4a56c867157a559722b7b350b668a0b8258209180d818e69cd997e34663c418a648c076f2e19cd4194e486e159d8580bc6cda5840af668e57c98f0c3d9b47c66eb9271213c39b4ea1b4d543b0892f03985edcef4216d1f98f7b731eedc260a2154124b5cab015bfeaf694d58966d124ad2ff60f0382582089c29f8c4af27b7accbe589747820134ebbaa1caf3ce949270a3d0c7dcfd541b58401ad69342385ba6c3bef937a79456d7280c0d539128072db15db120b1579c46ba95d18c1fa073d7dbffb4d975b1e02ebb7372936940cff0a96fce950616d2f504825820f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc855840638f7410929e7eab565b1451effdfbeea2a8839f7cfcc4c4483c4931d489547a2e94b73e4b15f8494de7f42ea31e573c459a9a7e5269af17b0978e70567de80e8258208b53207629f9a30e4b2015044f337c01735abe67243c19470c9dae8c7b73279858400c4ed03254c33a19256b7a3859079a9b75215cad83871a9b74eb51d8bcab52911c37ea5c43bdd212d006d1e6670220ff1d03714addf94f490e482edacbb08f068258205fddeedade2714d6db2f9e1104743d2d8d818ecddc306e176108db14caadd4415840bf48f5dd577b5cb920bfe60e13c8b1b889366c23e2f2e28d51814ed23def3a0ff4a1964f806829d40180d83b5230728409c1f18ddb5a61c44e614b823bd43f01825820cbc6b506e94fbefe442eecee376f3b3ebaf89415ef5cd2efb666e06ddae48393584089bff8f81a20b22f2c3f8a2288b15f1798b51f3363e0437a46c0a2e4e283b7c1018eba0b2b192d6d522ac8df2f2e95b4c8941b387cda89857ab0ae77db14780c825820e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d158402643ac53dd4da4f6e80fb192b2bf7d1dd9a333bbacea8f07531ba450dd8fb93e481589d370a6ef33a97e03b2f5816e4b2c6a8abf606a859108ba6f416e530d07f6'; + describe('Transaction', () => { it('round trip serializations produce the same CBOR output', () => { const tx = Transaction.fromCbor(TxCBOR(TX)); @@ -21,6 +26,22 @@ describe('Transaction', () => { expect(tx.toCore()).toEqual(babbageTx); }); + it('correctly deserialize a CBOR transaction that sets entropy protocol param to empty', () => { + const tx = Transaction.fromCbor(TxCBOR(TX_SET_ENTROPY_TO_EMPTY)); + + expect(tx.getId()).toEqual('fc863a441b55acceebb7d25c81ff7259e4fc9b92fbdf6d594118fb8f1110a78c'); + + const update = tx.body()?.update()?.toCore(); + expect(update).toBeDefined(); + + const extraEntropy = update?.proposedProtocolParameterUpdates?.get( + Crypto.Hash28ByteBase16('162f94554ac8c225383a2248c245659eda870eaa82d0ef25fc7dcd82') + )?.extraEntropy; + + expect(extraEntropy).toBeDefined(); + expect(extraEntropy).toEqual(''); + }); + it('correctly converts from a Core transaction', () => { const tx = Transaction.fromCore(coreTx);