From 4f9ba2aca2ea3fec971f33fa28ef9dfefc1484cd Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Wed, 5 Jun 2024 17:48:16 +0700 Subject: [PATCH 01/13] feat: query constitution, dRep state, gov state --- .../localstate/queries/ConstitutionQuery.java | 50 ++++++++ .../queries/ConstitutionResult.java | 14 +++ .../localstate/queries/DRepStateQuery.java | 73 +++++++++++ .../queries/DRepStateQueryResult.java | 23 ++++ .../localstate/queries/GovStateQuery.java | 35 ++++++ .../localstate/queries/GovStateResult.java | 22 ++++ .../localstate/queries/model/DRepState.java | 18 +++ .../localstate/queries/model/RatifyState.java | 5 + .../bloxbean/cardano/yaci/core/BaseTest.java | 2 + .../localstate/LocalStateQueryAgentIT.java | 114 +++++++++++++++++- 10 files changed, 352 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionQuery.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionResult.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionQuery.java new file mode 100644 index 00000000..378718af --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionQuery.java @@ -0,0 +1,50 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import co.nstant.in.cbor.model.Array; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.UnsignedInteger; +import com.bloxbean.cardano.yaci.core.model.governance.Anchor; +import com.bloxbean.cardano.yaci.core.model.serializers.governance.AnchorSerializer; +import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; +import lombok.ToString; + +import java.util.List; + +@Getter +@AllArgsConstructor +@ToString +// ouroboros-consensus-cardano/src/shelley/Ouroboros/Consensus/Shelley/Ledger/Query.hs +public class ConstitutionQuery implements EraQuery { + @NonNull + private Era era; + + public ConstitutionQuery() { + this.era = Era.Conway; + } + + @Override + public DataItem serialize(AcceptVersion protocolVersion) { + Array queryArray = new Array(); + queryArray.add(new UnsignedInteger(23)); + + return wrapWithOuterArray(queryArray); + } + + @Override + public ConstitutionResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { + List dataItemList = ((Array)di[0]).getDataItems(); + + int type = ((UnsignedInteger)dataItemList.get(0)).getValue().intValue(); //4 + + List resultDIList = ((Array)dataItemList.get(1)).getDataItems(); + var items = (Array)resultDIList.get(0); + + Anchor anchor = AnchorSerializer.INSTANCE.deserializeDI(items.getDataItems().get(0)); + return new ConstitutionResult(anchor); + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionResult.java new file mode 100644 index 00000000..812f592d --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/ConstitutionResult.java @@ -0,0 +1,14 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import com.bloxbean.cardano.yaci.core.model.governance.Anchor; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@Getter +@AllArgsConstructor +@ToString +public class ConstitutionResult implements QueryResult { + private Anchor anchor; +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java new file mode 100644 index 00000000..b2009c94 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java @@ -0,0 +1,73 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + + +import co.nstant.in.cbor.model.Array; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.Map; +import co.nstant.in.cbor.model.UnsignedInteger; +import com.bloxbean.cardano.yaci.core.model.Credential; +import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.DRepState; +import com.bloxbean.cardano.yaci.core.util.CborSerializationUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +@Getter +@AllArgsConstructor +public class DRepStateQuery implements EraQuery { + private Era era; + private List dRepCreds; + + public DRepStateQuery(List dRepCreds) { + this(Era.Conway, dRepCreds); + } + + @Override + public DataItem serialize(AcceptVersion protocolVersion) { + Array array = new Array(); + array.add(new UnsignedInteger(25)); + + Array dRepCredArray = new Array(); + + dRepCreds.forEach(dRepCred -> dRepCredArray.add(dRepCred.serialize())); + + dRepCredArray.setTag(258); + + array.add(dRepCredArray); + + return wrapWithOuterArray(array); + } + + @Override + public DRepStateQueryResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { + DRepStateQueryResult result = new DRepStateQueryResult(); + var array = (Array) di[0]; + var drepStateArray = (Array) array.getDataItems().get(1); + + drepStateArray.getDataItems().forEach(dataItem -> { + var map = (Map)dataItem; + var key = (List)map.getKeys(); + var itemDI = (Array)key.get(0); + String dRepHash = CborSerializationUtil.toHex(itemDI.getDataItems().get(1)); + var value = (Array) map.get(itemDI); + Integer expiry = CborSerializationUtil.toInt(value.getDataItems().get(0)); + // TODO: anchor + BigInteger deposit = CborSerializationUtil.toBigInteger(value.getDataItems().get(2)); + var dRepState = DRepState.builder() + .dRepHash(dRepHash) + .deposit(deposit) + .expiry(expiry) + .build(); + + result.addDRepState(dRepState); + }); + + return result; + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java new file mode 100644 index 00000000..fd63e5ea --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java @@ -0,0 +1,23 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.DRepState; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Setter +@Getter +public class DRepStateQueryResult implements QueryResult { + List dRepStates; + + public DRepStateQueryResult() { + this.dRepStates = new ArrayList<>(); + } + + public void addDRepState(DRepState dRepState) { + dRepStates.add(dRepState); + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java new file mode 100644 index 00000000..9114cc22 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -0,0 +1,35 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import co.nstant.in.cbor.model.Array; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.UnsignedInteger; +import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@Getter +@AllArgsConstructor +@ToString +public class GovStateQuery implements EraQuery { + private Era era; + + public GovStateQuery() { + this.era = Era.Conway; + } + + @Override + public DataItem serialize(AcceptVersion protocolVersion) { + Array queryArray = new Array(); + queryArray.add(new UnsignedInteger(24)); + + return wrapWithOuterArray(queryArray); + } + + @Override + public ConstitutionResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { + throw new UnsupportedOperationException("Not implemented yet"); + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java new file mode 100644 index 00000000..c8674048 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java @@ -0,0 +1,22 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import com.bloxbean.cardano.client.api.model.ProtocolParams; +import com.bloxbean.cardano.yaci.core.model.governance.Committee; +import com.bloxbean.cardano.yaci.core.model.governance.Constitution; +import com.bloxbean.cardano.yaci.core.model.governance.ProposalProcedure; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.RatifyState; +import lombok.Getter; + +import java.util.List; + +@Getter +public class GovStateResult implements QueryResult { + private Committee committee; + private Constitution constitution; + private ProtocolParams currentPParams; + private ProtocolParams futurePParams; + private ProtocolParams previousPParams; + private RatifyState nextRatifyState; + private List proposals; +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java new file mode 100644 index 00000000..9a9d5b24 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java @@ -0,0 +1,18 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; + +import com.bloxbean.cardano.yaci.core.model.governance.Anchor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigInteger; + +@Getter +@Setter +@Builder +public class DRepState { + private String dRepHash; + private Anchor anchor; + private BigInteger deposit; + private Integer expiry; +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java new file mode 100644 index 00000000..85d17573 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java @@ -0,0 +1,5 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; + +public class RatifyState { + // TODO: Implement me +} diff --git a/core/src/test/java/com/bloxbean/cardano/yaci/core/BaseTest.java b/core/src/test/java/com/bloxbean/cardano/yaci/core/BaseTest.java index dd844afc..ac7c1256 100644 --- a/core/src/test/java/com/bloxbean/cardano/yaci/core/BaseTest.java +++ b/core/src/test/java/com/bloxbean/cardano/yaci/core/BaseTest.java @@ -7,7 +7,9 @@ public class BaseTest { protected String node = Constants.PREPROD_IOHK_RELAY_ADDR; protected int nodePort = Constants.PREPROD_IOHK_RELAY_PORT; protected long protocolMagic = Constants.PREPROD_PROTOCOL_MAGIC; + protected long sanchoProtocolMagic = Constants.SANCHONET_PROTOCOL_MAGIC; protected Point knownPoint = new Point(13003663, "b896e43a25de269cfc47be7afbcbf00cad41a5011725c2732393f1b4508cf41d"); protected String nodeSocketFile = "/Users/satya/work/cardano-node/prepod/db/node.socket"; + protected String sanchoNodeSocketFile = "/Users/satya/work/cardano-node/sanchonet/db/node.socket"; } diff --git a/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java b/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java index 0984c876..70ed4198 100644 --- a/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java +++ b/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java @@ -1,24 +1,25 @@ package com.bloxbean.cardano.yaci.core.protocol.localstate; import com.bloxbean.cardano.yaci.core.BaseTest; +import com.bloxbean.cardano.yaci.core.model.Credential; +import com.bloxbean.cardano.yaci.core.model.certs.StakeCredType; import com.bloxbean.cardano.yaci.core.network.UnixSocketNodeClient; import com.bloxbean.cardano.yaci.core.protocol.chainsync.messages.Point; import com.bloxbean.cardano.yaci.core.protocol.handshake.HandshakeAgent; import com.bloxbean.cardano.yaci.core.protocol.handshake.HandshakeAgentListener; import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.Reason; import com.bloxbean.cardano.yaci.core.protocol.handshake.util.N2CVersionTableConstant; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Query; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; import com.bloxbean.cardano.yaci.core.protocol.localstate.messages.MsgFailure; -import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.BlockHeightQuery; -import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.ChainPointQuery; -import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.SystemStartQuery; -import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.SystemStartResult; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.*; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -380,4 +381,109 @@ public void resultReceived(Query query, QueryResult result) { n2CClient.shutdown(); } + + @Test + void constitutionQuery_shouldReturn_Constitution() throws InterruptedException { + HandshakeAgent handshakeAgent = new HandshakeAgent(N2CVersionTableConstant.v1AndAbove(sanchoProtocolMagic)); + LocalStateQueryAgent localStateQueryAgent = new LocalStateQueryAgent(); + + UnixSocketNodeClient n2CClient = new UnixSocketNodeClient(sanchoNodeSocketFile, handshakeAgent, localStateQueryAgent); + + CountDownLatch countDownLatch = new CountDownLatch(2); + handshakeAgent.addListener(new HandshakeAgentListener() { + @Override + public void handshakeOk() { + log.info("HANDSHAKE Successful"); + localStateQueryAgent.acquire(); + localStateQueryAgent.sendNextMessage(); + } + + @Override + public void handshakeError(Reason reason) { + log.info("ERROR {}", reason); + } + }); + + AtomicBoolean failed = new AtomicBoolean(false); + localStateQueryAgent.addListener(new LocalStateQueryListener() { + @Override + public void acquireFailed(MsgFailure.Reason reason) { + countDownLatch.countDown(); + failed.set(true); + } + + @Override + public void acquired(Point point) { + countDownLatch.countDown(); + localStateQueryAgent.query(new ConstitutionQuery(Era.Conway)); + localStateQueryAgent.sendNextMessage(); + } + + @Override + public void resultReceived(Query query, QueryResult result) { + System.out.println("Query >> " + query); + System.out.println("Result >> " + result); + System.out.println("Result : " + result); + countDownLatch.countDown(); + } + }); + + n2CClient.start(); + countDownLatch.await(20, TimeUnit.SECONDS); + n2CClient.shutdown(); + } + + @Test + void dRepStateQuery_shouldReturn_dRepStateList() throws InterruptedException { + HandshakeAgent handshakeAgent = new HandshakeAgent(N2CVersionTableConstant.v1AndAbove(sanchoProtocolMagic)); + LocalStateQueryAgent localStateQueryAgent = new LocalStateQueryAgent(); + + UnixSocketNodeClient n2CClient = new UnixSocketNodeClient(sanchoNodeSocketFile, handshakeAgent, localStateQueryAgent); + + CountDownLatch countDownLatch = new CountDownLatch(2); + handshakeAgent.addListener(new HandshakeAgentListener() { + @Override + public void handshakeOk() { + log.info("HANDSHAKE Successful"); + localStateQueryAgent.acquire(); + localStateQueryAgent.sendNextMessage(); + } + + @Override + public void handshakeError(Reason reason) { + log.info("ERROR {}", reason); + } + }); + + AtomicBoolean failed = new AtomicBoolean(false); + localStateQueryAgent.addListener(new LocalStateQueryListener() { + @Override + public void acquireFailed(MsgFailure.Reason reason) { + countDownLatch.countDown(); + failed.set(true); + } + + @Override + public void acquired(Point point) { + countDownLatch.countDown(); + localStateQueryAgent.query(new DRepStateQuery(List.of(Credential + .builder() + .type(StakeCredType.ADDR_KEYHASH) + .hash("11b2324445c59782060c4201838c6390bb9d8220cf46538e4f2a73ea").build()))); + localStateQueryAgent.sendNextMessage(); + } + + @Override + public void resultReceived(Query query, QueryResult result) { + System.out.println("Query >> " + query); + System.out.println("Result >> " + result); + countDownLatch.countDown(); + } + }); + + n2CClient.start(); + countDownLatch.await(20, TimeUnit.SECONDS); + n2CClient.shutdown(); + } + } From 062555ae9576262a90301938b015c899d7aed789 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Fri, 14 Jun 2024 10:38:01 +0700 Subject: [PATCH 02/13] chore: update gov state query impl --- .../localstate/queries/GovStateQuery.java | 348 +++++++++++++++++- .../localstate/queries/GovStateResult.java | 10 +- 2 files changed, 348 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index 9114cc22..69ea37dd 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -1,19 +1,38 @@ package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; -import co.nstant.in.cbor.model.Array; -import co.nstant.in.cbor.model.DataItem; -import co.nstant.in.cbor.model.UnsignedInteger; +import co.nstant.in.cbor.model.*; +import com.bloxbean.cardano.client.util.Tuple; +import com.bloxbean.cardano.yaci.core.model.DrepVoteThresholds; +import com.bloxbean.cardano.yaci.core.model.PoolVotingThresholds; +import com.bloxbean.cardano.yaci.core.model.ProtocolParamUpdate; +import com.bloxbean.cardano.yaci.core.model.governance.Anchor; +import com.bloxbean.cardano.yaci.core.model.governance.Committee; +import com.bloxbean.cardano.yaci.core.model.governance.Constitution; +import com.bloxbean.cardano.yaci.core.model.serializers.governance.AnchorSerializer; import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import com.bloxbean.cardano.yaci.core.util.CborSerializationUtil; +import com.bloxbean.cardano.yaci.core.util.HexUtil; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.ToString; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; + +import static com.bloxbean.cardano.yaci.core.protocol.handshake.util.N2CVersionTableConstant.PROTOCOL_V14; +import static com.bloxbean.cardano.yaci.core.protocol.handshake.util.N2CVersionTableConstant.PROTOCOL_V15; +import static com.bloxbean.cardano.yaci.core.util.CborSerializationUtil.*; +import static com.bloxbean.cardano.yaci.core.util.CborSerializationUtil.toRationalNumber; + @Getter @AllArgsConstructor @ToString -public class GovStateQuery implements EraQuery { +public class GovStateQuery implements EraQuery { private Era era; public GovStateQuery() { @@ -29,7 +48,324 @@ public DataItem serialize(AcceptVersion protocolVersion) { } @Override - public ConstitutionResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { - throw new UnsupportedOperationException("Not implemented yet"); + public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { + GovStateResult govStateResult = new GovStateResult(); + Array array = (Array) di[0]; + Array resultArray = (Array) ((Array) array.getDataItems().get(1)).getDataItems().get(0); + + // committee + Array committeeResult = (Array) resultArray.getDataItems().get(1); + Array committeeArr = (Array) committeeResult.getDataItems().get(0); + var committeeThresholdDI = (RationalNumber) committeeArr.getDataItems().get(1); + BigDecimal committeeThreshold = toRationalNumber(committeeThresholdDI); + // TODO: committee list + Committee committee = Committee.builder() + .committeeColdCredentialEpoch(new HashMap<>()) + .threshold(committeeThreshold) + .build(); + govStateResult.setCommittee(committee); + + // constitution + Array constitutionArr = (Array) resultArray.getDataItems().get(2); + var constitutionDI = constitutionArr.getDataItems().get(0); + + Anchor anchor = AnchorSerializer.INSTANCE.deserializeDI(constitutionDI); + Constitution constitution = Constitution.builder().anchor(anchor).build(); + govStateResult.setConstitution(constitution); + + // current protocol params + Array currentPParams = (Array) resultArray.getDataItems().get(3); + List paramsDIList = currentPParams.getDataItems(); + + ProtocolParamUpdate currentProtocolParam = deserializePPResult(paramsDIList); + + govStateResult.setCurrentPParams(currentProtocolParam); + + // TODO: future protocol params + // TODO: next ratify state + + // previous protocol params + Array prevPParams = (Array) resultArray.getDataItems().get(4); + paramsDIList = prevPParams.getDataItems(); + ProtocolParamUpdate prevProtocolParam = deserializePPResult(paramsDIList); + + govStateResult.setPreviousPParams(prevProtocolParam); + + // TODO: proposals + return govStateResult; + } + + public ProtocolParamUpdate deserializePPResult(List paramsDIList) { + DataItem itemDI = paramsDIList.get(0); + Integer minFeeA = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(1); + Integer minFeeB = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(2); + Integer maxBlockSize = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(3); + Integer maxTxSize = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(4); + Integer maxBlockHeaderSize = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(5); + BigInteger keyDeposit = itemDI != null ? toBigInteger(itemDI) : null; + + itemDI = paramsDIList.get(6); + BigInteger poolDeposit = itemDI != null ? toBigInteger(itemDI) : null; + + itemDI = paramsDIList.get(7); + Integer maxEpoch = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(8); + Integer nOpt = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(9); + BigDecimal poolPledgeInfluence = itemDI != null ? toRationalNumber(itemDI) : null; + + itemDI = paramsDIList.get(10); + BigDecimal expansionRate = itemDI != null ? toRationalNumber(itemDI) : null; + + itemDI = paramsDIList.get(11); + BigDecimal treasuryGrowthRate = itemDI != null ? toRationalNumber(itemDI) : null; + + Integer protocolMajorVersion = null; + Integer protocolMinorVersion = null; + itemDI = paramsDIList.get(12); + if (itemDI != null) { + List protocolVersions = ((Array) itemDI).getDataItems(); + protocolMajorVersion = toInt(protocolVersions.get(0)); + protocolMinorVersion = toInt(protocolVersions.get(1)); + } + + itemDI = paramsDIList.get(13); + BigInteger minPoolCost = itemDI != null ? toBigInteger(itemDI) : null; + + itemDI = paramsDIList.get(14); + BigInteger adaPerUtxoBytes = itemDI != null ? toBigInteger(itemDI) : null; + + //CostModels + java.util.Map costModelMap = null; + itemDI = paramsDIList.get(15); + if (itemDI != null) { + costModelMap = new LinkedHashMap<>(); + Map itemDIMap = (Map) itemDI; + for (DataItem key : itemDIMap.getKeys()) { + Integer version = toInt(key); + String costModel = HexUtil.encodeHexString(CborSerializationUtil.serialize(itemDIMap.get(key))); + costModelMap.put(version, costModel); + } + } + + //exUnits prices + BigDecimal priceMem = null; + BigDecimal priceSteps = null; + itemDI = paramsDIList.get(16); + if (itemDI != null) { + List exUnitPriceList = ((Array) itemDI).getDataItems(); + Tuple tuple = getExUnitPrices(exUnitPriceList); + priceMem = tuple._1; + priceSteps = tuple._2; + } + + //max tx exunits + BigInteger maxTxExMem = null; + BigInteger maxTxExSteps = null; + itemDI = paramsDIList.get(17); + if (itemDI != null) { + List exUnits = ((Array) itemDI).getDataItems(); + Tuple tuple = getExUnits(exUnits); + maxTxExMem = tuple._1; + maxTxExSteps = tuple._2; + } + + //max block exunits + BigInteger maxBlockExMem = null; + BigInteger maxBlockExSteps = null; + itemDI = paramsDIList.get(18); + if (itemDI != null) { + List exUnits = ((Array) itemDI).getDataItems(); + Tuple tuple = getExUnits(exUnits); + maxBlockExMem = tuple._1; + maxBlockExSteps = tuple._2; + } + + itemDI = paramsDIList.get(19); + Long maxValueSize = itemDI != null ? toLong(itemDI) : null; + + itemDI = paramsDIList.get(20); + Integer collateralPercent = itemDI != null ? toInt(itemDI) : null; + + Integer maxCollateralInputs = null; + itemDI = paramsDIList.get(21); + maxCollateralInputs = itemDI != null ? toInt(itemDI) : null; + + //Pool Voting Threshold + itemDI = paramsDIList.get(22); + BigDecimal motionNoConfidence = null; + BigDecimal committeeNormal = null; + BigDecimal committeeNoConfidence = null; + BigDecimal hardForkInitiation = null; + BigDecimal ppSecurityGroup = null; + if (itemDI != null) { + List poolVotingThresholdList = ((Array) itemDI).getDataItems(); + if (poolVotingThresholdList.size() != 5) + throw new IllegalStateException("Invalid pool voting threshold list"); + + var pvtMotionNoConfidenceDI = (RationalNumber) poolVotingThresholdList.get(0); + var pvtCommitteeNormalDI = (RationalNumber) poolVotingThresholdList.get(1); + var pvtCommitteeNoConfidenceDI = (RationalNumber) poolVotingThresholdList.get(2); + var pvtHardForkInitiationDI = (RationalNumber) poolVotingThresholdList.get(3); + var pvtPPSecurityGroupDI = (RationalNumber) poolVotingThresholdList.get(4); + + motionNoConfidence = toRationalNumber(pvtMotionNoConfidenceDI); + committeeNormal = toRationalNumber(pvtCommitteeNormalDI); + committeeNoConfidence = toRationalNumber(pvtCommitteeNoConfidenceDI); + hardForkInitiation = toRationalNumber(pvtHardForkInitiationDI); + ppSecurityGroup = toRationalNumber(pvtPPSecurityGroupDI); + } + + //DRep voting thresholds + itemDI = paramsDIList.get(23); + BigDecimal dvtMotionNoConfidence = null; + BigDecimal dvtCommitteeNormal = null; + BigDecimal dvtCommitteeNoConfidence = null; + BigDecimal dvtUpdateToConstitution = null; + BigDecimal dvtHardForkInitiation = null; + BigDecimal dvtPPNetworkGroup = null; + BigDecimal dvtPPEconomicGroup = null; + BigDecimal dvtPPTechnicalGroup = null; + BigDecimal dvtPPGovGroup = null; + BigDecimal dvtTreasuryWithdrawal = null; + + if (itemDI != null) { + List dRepVotingThresholdList = ((Array) itemDI).getDataItems(); + if (dRepVotingThresholdList.size() != 10) + throw new IllegalStateException("Invalid dRep voting threshold list"); + + var dvtMotionNoConfidenceDI = (RationalNumber) dRepVotingThresholdList.get(0); + var dvtCommitteeNormalDI = (RationalNumber) dRepVotingThresholdList.get(1); + var dvtCommitteeNoConfidenceDI = (RationalNumber) dRepVotingThresholdList.get(2); + var dvtUpdateToConstitutionDI = (RationalNumber) dRepVotingThresholdList.get(3); + var dvtHardForkInitiationDI = (RationalNumber) dRepVotingThresholdList.get(4); + var dvtPPNetworkGroupDI = (RationalNumber) dRepVotingThresholdList.get(5); + var dvtPPEconomicGroupDI = (RationalNumber) dRepVotingThresholdList.get(6); + var dvtPPTechnicalGroupDI = (RationalNumber) dRepVotingThresholdList.get(7); + var dvtPPGovGroupDI = (RationalNumber) dRepVotingThresholdList.get(8); + var dvtTreasuryWithdrawalDI = (RationalNumber) dRepVotingThresholdList.get(9); + + dvtMotionNoConfidence = toRationalNumber(dvtMotionNoConfidenceDI); + dvtCommitteeNormal = toRationalNumber(dvtCommitteeNormalDI); + dvtCommitteeNoConfidence = toRationalNumber(dvtCommitteeNoConfidenceDI); + dvtUpdateToConstitution = toRationalNumber(dvtUpdateToConstitutionDI); + dvtHardForkInitiation = toRationalNumber(dvtHardForkInitiationDI); + dvtPPNetworkGroup = toRationalNumber(dvtPPNetworkGroupDI); + dvtPPEconomicGroup = toRationalNumber(dvtPPEconomicGroupDI); + dvtPPTechnicalGroup = toRationalNumber(dvtPPTechnicalGroupDI); + dvtPPGovGroup = toRationalNumber(dvtPPGovGroupDI); + dvtTreasuryWithdrawal = toRationalNumber(dvtTreasuryWithdrawalDI); + } + + itemDI = paramsDIList.get(24); + Integer minCommitteeSize = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(25); + Integer committeeTermLimit = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(26); + Integer governanceActionValidityPeriod = itemDI != null ? toInt(itemDI) : null; + + itemDI = paramsDIList.get(27); + BigInteger governanceActionDeposit = itemDI != null ? toBigInteger(itemDI) : null; + + itemDI = paramsDIList.get(28); + BigInteger drepDeposit = itemDI != null ? toBigInteger(itemDI) : null; + + itemDI = paramsDIList.get(29); + Integer drepInactivityPeriod = itemDI != null ? toInt(itemDI) : null; + + BigDecimal minFeeRefScriptCostPerByte = null; //TODO -- Remove if condition once this is available in the node release + if (paramsDIList.size() > 30) { + itemDI = paramsDIList.get(30); + minFeeRefScriptCostPerByte = itemDI != null ? toRationalNumber(itemDI) : null; + } + + return ProtocolParamUpdate.builder() + .minFeeA(minFeeA) + .minFeeB(minFeeB) + .maxBlockSize(maxBlockSize) + .maxTxSize(maxTxSize) + .maxBlockHeaderSize(maxBlockHeaderSize) + .keyDeposit(keyDeposit) + .poolDeposit(poolDeposit) + .maxEpoch(maxEpoch) + .nOpt(nOpt) + .poolPledgeInfluence(poolPledgeInfluence) + .expansionRate(expansionRate) + .treasuryGrowthRate(treasuryGrowthRate) + .protocolMajorVer(protocolMajorVersion) + .protocolMinorVer(protocolMinorVersion) + .minPoolCost(minPoolCost) + .adaPerUtxoByte(adaPerUtxoBytes) + .costModels(costModelMap) + .priceMem(priceMem) + .priceStep(priceSteps) + .maxTxExMem(maxTxExMem) + .maxTxExSteps(maxTxExSteps) + .maxBlockExMem(maxBlockExMem) + .maxBlockExSteps(maxBlockExSteps) + .maxValSize(maxValueSize) + .collateralPercent(collateralPercent) + .maxCollateralInputs(maxCollateralInputs) + .poolVotingThresholds(PoolVotingThresholds.builder() + .pvtMotionNoConfidence(motionNoConfidence) + .pvtCommitteeNormal(committeeNormal) + .pvtCommitteeNoConfidence(committeeNoConfidence) + .pvtHardForkInitiation(hardForkInitiation) + .pvtPPSecurityGroup(ppSecurityGroup) + .build()) + .drepVotingThresholds(DrepVoteThresholds.builder() + .dvtMotionNoConfidence(dvtMotionNoConfidence) + .dvtCommitteeNormal(dvtCommitteeNormal) + .dvtCommitteeNoConfidence(dvtCommitteeNoConfidence) + .dvtUpdateToConstitution(dvtUpdateToConstitution) + .dvtHardForkInitiation(dvtHardForkInitiation) + .dvtPPNetworkGroup(dvtPPNetworkGroup) + .dvtPPEconomicGroup(dvtPPEconomicGroup) + .dvtPPTechnicalGroup(dvtPPTechnicalGroup) + .dvtPPGovGroup(dvtPPGovGroup) + .dvtTreasuryWithdrawal(dvtTreasuryWithdrawal) + .build()) + .committeeMinSize(minCommitteeSize) + .committeeMaxTermLength(committeeTermLimit) + .govActionLifetime(governanceActionValidityPeriod) + .govActionDeposit(governanceActionDeposit) + .drepDeposit(drepDeposit) + .drepActivity(drepInactivityPeriod) + .minFeeRefScriptCostPerByte(minFeeRefScriptCostPerByte) + .build(); + } + + private Tuple getExUnits(List exunits) { + BigInteger mem = toBigInteger(exunits.get(0)); + + BigInteger steps = null; + if (exunits.size() > 1) + steps = toBigInteger(exunits.get(1)); + + return new Tuple<>(mem, steps); + } + + private Tuple getExUnitPrices(List exunits) { + RationalNumber memPriceRN = (RationalNumber) exunits.get(0); + RationalNumber stepPriceRN = (RationalNumber) exunits.get(1); + + BigDecimal memPrice = toRationalNumber(memPriceRN); + BigDecimal stepPrice = toRationalNumber(stepPriceRN); + + return new Tuple<>(memPrice, stepPrice); } } diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java index c8674048..f43c6b96 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java @@ -1,22 +1,24 @@ package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; -import com.bloxbean.cardano.client.api.model.ProtocolParams; +import com.bloxbean.cardano.yaci.core.model.ProtocolParamUpdate; import com.bloxbean.cardano.yaci.core.model.governance.Committee; import com.bloxbean.cardano.yaci.core.model.governance.Constitution; import com.bloxbean.cardano.yaci.core.model.governance.ProposalProcedure; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.RatifyState; import lombok.Getter; +import lombok.Setter; import java.util.List; @Getter +@Setter public class GovStateResult implements QueryResult { private Committee committee; private Constitution constitution; - private ProtocolParams currentPParams; - private ProtocolParams futurePParams; - private ProtocolParams previousPParams; + private ProtocolParamUpdate currentPParams; + private ProtocolParamUpdate futurePParams; + private ProtocolParamUpdate previousPParams; private RatifyState nextRatifyState; private List proposals; } From 2e6c1420fe931df5fd1a621eeefe34421b747c58 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Thu, 4 Jul 2024 11:23:11 +0700 Subject: [PATCH 03/13] chore: init drep stake distribution query --- .../queries/DRepStakeDistributionQuery.java | 46 +++++++++++++++++++ .../queries/DRepStakeDistributionResult.java | 7 +++ 2 files changed, 53 insertions(+) create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java new file mode 100644 index 00000000..62ac398c --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java @@ -0,0 +1,46 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import co.nstant.in.cbor.model.Array; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.UnsignedInteger; +import com.bloxbean.cardano.client.transaction.spec.governance.DRep; +import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +@Getter +@ToString +@AllArgsConstructor +@Slf4j +public class DRepStakeDistributionQuery implements EraQuery { + private Era era; + private List dReps; + + public DRepStakeDistributionQuery(List dReps) { + this(Era.Conway, dReps); + } + + @Override + public DataItem serialize(AcceptVersion protocolVersion) { + Array array = new Array(); + array.add(new UnsignedInteger(26)); + + Array dRepArray = new Array(); + dReps.forEach(dRep -> dRepArray.add(dRep.serialize())); + + array.add(dRepArray); + + return wrapWithOuterArray(array); + } + + @Override + public DRepStakeDistributionResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { + throw new UnsupportedOperationException("Not implemented yet"); + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java new file mode 100644 index 00000000..97ac8b35 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java @@ -0,0 +1,7 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; + +public class DRepStakeDistributionResult implements QueryResult { + +} From c1ef70755532925950a253c1549d3a2ca2d4db36 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Fri, 5 Jul 2024 19:31:53 +0700 Subject: [PATCH 04/13] chore: update gov state query --- .../localstate/queries/GovStateQuery.java | 156 ++++++++++++++++-- .../localstate/queries/GovStateResult.java | 4 +- .../localstate/queries/model/EnactState.java | 22 +++ .../localstate/queries/model/Proposal.java | 23 +++ .../queries/model/ProposalType.java | 5 + .../localstate/queries/model/RatifyState.java | 15 +- 6 files changed, 207 insertions(+), 18 deletions(-) create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/ProposalType.java diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index 69ea37dd..2a383705 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -2,16 +2,22 @@ import co.nstant.in.cbor.model.*; import com.bloxbean.cardano.client.util.Tuple; +import com.bloxbean.cardano.yaci.core.model.Credential; import com.bloxbean.cardano.yaci.core.model.DrepVoteThresholds; import com.bloxbean.cardano.yaci.core.model.PoolVotingThresholds; import com.bloxbean.cardano.yaci.core.model.ProtocolParamUpdate; +import com.bloxbean.cardano.yaci.core.model.certs.StakeCredType; import com.bloxbean.cardano.yaci.core.model.governance.Anchor; import com.bloxbean.cardano.yaci.core.model.governance.Committee; import com.bloxbean.cardano.yaci.core.model.governance.Constitution; +import com.bloxbean.cardano.yaci.core.model.governance.GovActionId; import com.bloxbean.cardano.yaci.core.model.serializers.governance.AnchorSerializer; import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.EnactState; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.ProposalType; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.RatifyState; import com.bloxbean.cardano.yaci.core.util.CborSerializationUtil; import com.bloxbean.cardano.yaci.core.util.HexUtil; import lombok.AllArgsConstructor; @@ -20,14 +26,12 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; -import static com.bloxbean.cardano.yaci.core.protocol.handshake.util.N2CVersionTableConstant.PROTOCOL_V14; -import static com.bloxbean.cardano.yaci.core.protocol.handshake.util.N2CVersionTableConstant.PROTOCOL_V15; import static com.bloxbean.cardano.yaci.core.util.CborSerializationUtil.*; -import static com.bloxbean.cardano.yaci.core.util.CborSerializationUtil.toRationalNumber; @Getter @AllArgsConstructor @@ -55,22 +59,15 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ // committee Array committeeResult = (Array) resultArray.getDataItems().get(1); - Array committeeArr = (Array) committeeResult.getDataItems().get(0); - var committeeThresholdDI = (RationalNumber) committeeArr.getDataItems().get(1); - BigDecimal committeeThreshold = toRationalNumber(committeeThresholdDI); - // TODO: committee list - Committee committee = Committee.builder() - .committeeColdCredentialEpoch(new HashMap<>()) - .threshold(committeeThreshold) - .build(); + Array committeeDI = (Array) committeeResult.getDataItems().get(0); + Committee committee = deserializeCommitteeResult(committeeDI.getDataItems()); govStateResult.setCommittee(committee); // constitution Array constitutionArr = (Array) resultArray.getDataItems().get(2); var constitutionDI = constitutionArr.getDataItems().get(0); - Anchor anchor = AnchorSerializer.INSTANCE.deserializeDI(constitutionDI); - Constitution constitution = Constitution.builder().anchor(anchor).build(); + Constitution constitution = deserializeConstitutionResult(constitutionDI); govStateResult.setConstitution(constitution); // current protocol params @@ -82,7 +79,82 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ govStateResult.setCurrentPParams(currentProtocolParam); // TODO: future protocol params - // TODO: next ratify state + + // next ratify state + Array nextRatifyStateDI = (Array) ((Array)resultArray.getDataItems().get(6)).getDataItems().get(1); + + // next ratify state - enacted gov actions + List enactedGovActions = deserializeGovActionIdListResult(nextRatifyStateDI.getDataItems().get(1)); + + // next ratify state - expired gov actions + List expiredGovActions = deserializeGovActionIdListResult(nextRatifyStateDI.getDataItems().get(2)); + + // next ratify state - next enact state + var nextEnactStateDI = (Array)nextRatifyStateDI.getDataItems().get(0); + + // next enact state - committee + var nextEnactStateCommitteeArr = (Array) nextEnactStateDI.getDataItems().get(0); + Committee nextEnactStateCommittee = deserializeCommitteeResult( + ((Array)nextEnactStateCommitteeArr.getDataItems().get(0)).getDataItems()); + + // next enact state - constitution + var nextEnactStateConstitutionArr = (Array)nextEnactStateDI.getDataItems().get(1); + Constitution nextEnactStateConstitution = deserializeConstitutionResult(nextEnactStateConstitutionArr.getDataItems().get(0)); + + // next enact state - current protocol params + ProtocolParamUpdate nextEnactStateCurrentPParams = deserializePPResult( + ((Array)nextEnactStateDI.getDataItems().get(2)).getDataItems()); + // next enact state - prev protocol params + ProtocolParamUpdate nextEnactStatePrevPParams = deserializePPResult( + ((Array)nextEnactStateDI.getDataItems().get(3)).getDataItems()); + // next enact state - Prev govActionIds + java.util.Map prevGovActionIds = new HashMap<>(); + Array nextEnactStatePrevGovActionIds = (Array) nextEnactStateDI.getDataItems().get(6); + + prevGovActionIds.put(ProposalType.COMMITTEE, + deserializeGovActionIdListResult(nextEnactStatePrevGovActionIds.getDataItems().get(0)) + .stream() + .findFirst() + .orElse(null)); + + prevGovActionIds.put(ProposalType.HARD_FORK, + deserializeGovActionIdListResult(nextEnactStatePrevGovActionIds.getDataItems().get(1)) + .stream() + .findFirst() + .orElse(null)); + + prevGovActionIds.put(ProposalType.CONSTITUTION, + deserializeGovActionIdListResult(nextEnactStatePrevGovActionIds.getDataItems().get(1)) + .stream() + .findFirst() + .orElse(null)); + + prevGovActionIds.put(ProposalType.P_PARAM_UPDATE, + deserializeGovActionIdListResult(nextEnactStatePrevGovActionIds.getDataItems().get(1)) + .stream() + .findFirst() + .orElse(null)); + + // next ratify state - ratificationDelayed + var ratificationDelayedDI = nextRatifyStateDI.getDataItems().get(3); + Boolean ratificationDelayed = ratificationDelayedDI != null ? + (((SimpleValue) ratificationDelayedDI).getValue() == SimpleValueType.FALSE.getValue() ? Boolean.FALSE : Boolean.TRUE) + : null; + + RatifyState nextRatifyState = RatifyState.builder() + .ratificationDelayed(ratificationDelayed) + .nextEnactState(EnactState.builder() + .committee(nextEnactStateCommittee) + .constitution(nextEnactStateConstitution) + .currentPParams(nextEnactStateCurrentPParams) + .prevGovActionIds(prevGovActionIds) + .prevPParams(nextEnactStatePrevPParams) + .build()) + .enactedGovActions(enactedGovActions) + .expiredGovActions(expiredGovActions) + .build(); + + govStateResult.setNextRatifyState(nextRatifyState); // previous protocol params Array prevPParams = (Array) resultArray.getDataItems().get(4); @@ -90,8 +162,8 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ ProtocolParamUpdate prevProtocolParam = deserializePPResult(paramsDIList); govStateResult.setPreviousPParams(prevProtocolParam); - // TODO: proposals + return govStateResult; } @@ -368,4 +440,58 @@ private Tuple getExUnitPrices(List exunits) { return new Tuple<>(memPrice, stepPrice); } + + public Committee deserializeCommitteeResult(List committeeDIList) { + var committeeMapDI = (Map) committeeDIList.get(0); + java.util.Map committeeColdCredentialEpoch = new LinkedHashMap<>(); + + for (DataItem di : committeeMapDI.getKeys()) { + var key = (Array) di; + String credentialHash = HexUtil.encodeHexString(((ByteString)key.getDataItems().get(1)).getBytes()); + Credential credential = Credential.builder() + .type(StakeCredType.SCRIPTHASH) // todo: check type + .hash(credentialHash) + .build(); + var expiredEpochDI = committeeMapDI.get(key); + committeeColdCredentialEpoch.put(credential, toLong(expiredEpochDI)); + } + + var committeeThresholdDI = (RationalNumber) committeeDIList.get(1); + BigDecimal committeeThreshold = toRationalNumber(committeeThresholdDI); + + return Committee.builder() + .committeeColdCredentialEpoch(committeeColdCredentialEpoch) + .threshold(committeeThreshold) + .build(); + } + + public List deserializeGovActionIdListResult(DataItem govActionsDI) { + List govActionIds = new ArrayList<>(); + + Array govActionsArray = (Array) govActionsDI; + for (DataItem item : govActionsArray.getDataItems()) { + govActionIds.add(deserializeGovActionIdResult(item)); + } + + return govActionIds; + } + + public GovActionId deserializeGovActionIdResult(DataItem govActionId) { + Array govActionIdDI = (Array) govActionId; + + if (govActionIdDI.getDataItems().isEmpty()) { + return null; + } + + return GovActionId.builder() + .transactionId(HexUtil.encodeHexString(((ByteString) govActionIdDI.getDataItems().get(0)).getBytes())) + .gov_action_index(toInt(govActionIdDI.getDataItems().get(1))) + .build(); + } + + public Constitution deserializeConstitutionResult(DataItem constitutionDI) { + Anchor anchor = AnchorSerializer.INSTANCE.deserializeDI(constitutionDI); + return Constitution.builder().anchor(anchor).build(); + } + } diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java index f43c6b96..4b8fb29d 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java @@ -3,8 +3,8 @@ import com.bloxbean.cardano.yaci.core.model.ProtocolParamUpdate; import com.bloxbean.cardano.yaci.core.model.governance.Committee; import com.bloxbean.cardano.yaci.core.model.governance.Constitution; -import com.bloxbean.cardano.yaci.core.model.governance.ProposalProcedure; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.Proposal; import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.RatifyState; import lombok.Getter; import lombok.Setter; @@ -20,5 +20,5 @@ public class GovStateResult implements QueryResult { private ProtocolParamUpdate futurePParams; private ProtocolParamUpdate previousPParams; private RatifyState nextRatifyState; - private List proposals; + private List proposals; } diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java new file mode 100644 index 00000000..ceb1f75a --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java @@ -0,0 +1,22 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; + +import com.bloxbean.cardano.yaci.core.model.ProtocolParamUpdate; +import com.bloxbean.cardano.yaci.core.model.governance.Committee; +import com.bloxbean.cardano.yaci.core.model.governance.Constitution; +import com.bloxbean.cardano.yaci.core.model.governance.GovActionId; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +@Getter +@Setter +@Builder +public class EnactState { + private Committee committee; + private Constitution constitution; + private ProtocolParamUpdate currentPParams; + private ProtocolParamUpdate prevPParams; + private Map prevGovActionIds; +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java new file mode 100644 index 00000000..3cadda95 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java @@ -0,0 +1,23 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; + +import com.bloxbean.cardano.yaci.core.model.governance.Drep; +import com.bloxbean.cardano.yaci.core.model.governance.GovActionId; +import com.bloxbean.cardano.yaci.core.model.governance.ProposalProcedure; +import com.bloxbean.cardano.yaci.core.model.governance.Vote; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +@Getter +@Setter +@Builder +public class Proposal { + private GovActionId govActionId; + // TODO: committees votes; + private Map dRepVotes; + private ProposalProcedure proposalProcedure; + private Integer expiredAfter; + private Integer proposedIn; +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/ProposalType.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/ProposalType.java new file mode 100644 index 00000000..82513e45 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/ProposalType.java @@ -0,0 +1,5 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; + +public enum ProposalType { + COMMITTEE, CONSTITUTION, HARD_FORK, P_PARAM_UPDATE +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java index 85d17573..6eff33b6 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java @@ -1,5 +1,18 @@ package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; +import com.bloxbean.cardano.yaci.core.model.governance.GovActionId; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@Builder public class RatifyState { - // TODO: Implement me + private List enactedGovActions; + private List expiredGovActions; + private EnactState nextEnactState; + private Boolean ratificationDelayed; } From 939715bfff62eb70049562717277b9914c50329c Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 8 Jul 2024 15:07:12 +0700 Subject: [PATCH 05/13] chore: update gov state query --- .../localstate/queries/GovStateQuery.java | 60 +++++++++++++++++-- .../localstate/queries/model/Proposal.java | 1 + 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index 2a383705..7f6feceb 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -7,15 +7,13 @@ import com.bloxbean.cardano.yaci.core.model.PoolVotingThresholds; import com.bloxbean.cardano.yaci.core.model.ProtocolParamUpdate; import com.bloxbean.cardano.yaci.core.model.certs.StakeCredType; -import com.bloxbean.cardano.yaci.core.model.governance.Anchor; -import com.bloxbean.cardano.yaci.core.model.governance.Committee; -import com.bloxbean.cardano.yaci.core.model.governance.Constitution; -import com.bloxbean.cardano.yaci.core.model.governance.GovActionId; +import com.bloxbean.cardano.yaci.core.model.governance.*; import com.bloxbean.cardano.yaci.core.model.serializers.governance.AnchorSerializer; import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.EnactState; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.Proposal; import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.ProposalType; import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.RatifyState; import com.bloxbean.cardano.yaci.core.util.CborSerializationUtil; @@ -162,7 +160,56 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ ProtocolParamUpdate prevProtocolParam = deserializePPResult(paramsDIList); govStateResult.setPreviousPParams(prevProtocolParam); - // TODO: proposals + + // proposals + Array proposalArr = (Array)((Array) resultArray.getDataItems().get(0)).getDataItems().get(1); + + List proposals = new ArrayList<>(); + for (DataItem item : proposalArr.getDataItems()) { + if (item == SimpleValue.BREAK) { + continue; + } + var proposalDI = (Array) item; + // govActionId + GovActionId govActionId = deserializeGovActionIdResult(proposalDI.getDataItems().get(0)); + // proposalProcedure + var proposalProcedureDI = (Array) proposalDI.getDataItems().get(4); + + ProposalProcedure proposalProcedure = ProposalProcedure.builder() + .anchor(AnchorSerializer.INSTANCE.deserializeDI(proposalProcedureDI.getDataItems().get(3))) + .rewardAccount(HexUtil.encodeHexString(((ByteString) proposalProcedureDI.getDataItems().get(1)).getBytes())) + // TODO: 'govAction' field + .deposit(toBigInteger(proposalProcedureDI.getDataItems().get(0))) + .build(); + + // dRep votes + java.util.Map dRepVotes = new HashMap<>(); + var dRepVotesDI = (Map) proposalDI.getDataItems().get(2); + + for (DataItem key : dRepVotesDI.getKeys()) { + var credentialDI = (Array) key; + int credType = toInt(credentialDI.getDataItems().get(0)); + String credHash = HexUtil.encodeHexString(((ByteString)credentialDI.getDataItems().get(1)).getBytes()); + var voteDI = dRepVotesDI.get(credentialDI); + Vote vote = Vote.values()[toInt(voteDI)]; + dRepVotes.put(credType == 0 ? Drep.addrKeyHash(credHash) : Drep.scriptHash(credHash), vote); + } + + // expiredAfter + Integer expiredAfter = toInt(proposalDI.getDataItems().get(6)); + // proposedIn + Integer proposedIn = toInt(proposalDI.getDataItems().get(5)); + proposals.add( + Proposal.builder() + .dRepVotes(dRepVotes) + .proposalProcedure(proposalProcedure) + .govActionId(govActionId) + .expiredAfter(expiredAfter) + .proposedIn(proposedIn) + .build()); + } + + govStateResult.setProposals(proposals); return govStateResult; } @@ -447,9 +494,10 @@ public Committee deserializeCommitteeResult(List committeeDIList) { for (DataItem di : committeeMapDI.getKeys()) { var key = (Array) di; + int credType = toInt(key.getDataItems().get(0)); String credentialHash = HexUtil.encodeHexString(((ByteString)key.getDataItems().get(1)).getBytes()); Credential credential = Credential.builder() - .type(StakeCredType.SCRIPTHASH) // todo: check type + .type(credType == 1 ? StakeCredType.SCRIPTHASH: StakeCredType.ADDR_KEYHASH) .hash(credentialHash) .build(); var expiredEpochDI = committeeMapDI.get(key); diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java index 3cadda95..c1433859 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java @@ -16,6 +16,7 @@ public class Proposal { private GovActionId govActionId; // TODO: committees votes; + // TODO: stake pools votes private Map dRepVotes; private ProposalProcedure proposalProcedure; private Integer expiredAfter; From 32c85ab68fb65584358fff8de0b3ad753631d993 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 8 Jul 2024 17:49:07 +0700 Subject: [PATCH 06/13] chore: stake pool votes in gov state query --- .../protocol/localstate/queries/GovStateQuery.java | 12 ++++++++++++ .../protocol/localstate/queries/model/Proposal.java | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index 7f6feceb..8c9caa83 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -7,6 +7,7 @@ import com.bloxbean.cardano.yaci.core.model.PoolVotingThresholds; import com.bloxbean.cardano.yaci.core.model.ProtocolParamUpdate; import com.bloxbean.cardano.yaci.core.model.certs.StakeCredType; +import com.bloxbean.cardano.yaci.core.model.certs.StakePoolId; import com.bloxbean.cardano.yaci.core.model.governance.*; import com.bloxbean.cardano.yaci.core.model.serializers.governance.AnchorSerializer; import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; @@ -195,6 +196,16 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ dRepVotes.put(credType == 0 ? Drep.addrKeyHash(credHash) : Drep.scriptHash(credHash), vote); } + // stake pool votes + java.util.Map stakePoolVotes = new HashMap<>(); + var stakePoolVotesDI = (Map) proposalDI.getDataItems().get(3); + for (DataItem key : stakePoolVotesDI.getKeys()) { + String poolHash = HexUtil.encodeHexString(((ByteString)key).getBytes()); + var voteDI = stakePoolVotesDI.get(key); + Vote vote = Vote.values()[toInt(voteDI)]; + stakePoolVotes.put(StakePoolId.builder().poolKeyHash(poolHash).build(), vote); + } + // expiredAfter Integer expiredAfter = toInt(proposalDI.getDataItems().get(6)); // proposedIn @@ -202,6 +213,7 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ proposals.add( Proposal.builder() .dRepVotes(dRepVotes) + .stakePoolVotes(stakePoolVotes) .proposalProcedure(proposalProcedure) .govActionId(govActionId) .expiredAfter(expiredAfter) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java index c1433859..f5b07575 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java @@ -1,5 +1,6 @@ package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; +import com.bloxbean.cardano.yaci.core.model.certs.StakePoolId; import com.bloxbean.cardano.yaci.core.model.governance.Drep; import com.bloxbean.cardano.yaci.core.model.governance.GovActionId; import com.bloxbean.cardano.yaci.core.model.governance.ProposalProcedure; @@ -16,8 +17,8 @@ public class Proposal { private GovActionId govActionId; // TODO: committees votes; - // TODO: stake pools votes private Map dRepVotes; + private Map stakePoolVotes; private ProposalProcedure proposalProcedure; private Integer expiredAfter; private Integer proposedIn; From 9179e9f93fa8a7e42dab0edea507eb93c113cfb1 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 22 Jul 2024 11:14:57 +0700 Subject: [PATCH 07/13] chore: update deserializing future pp and enacted gov action --- .../localstate/queries/GovStateQuery.java | 117 ++++++++++-------- .../localstate/queries/model/RatifyState.java | 2 +- 2 files changed, 67 insertions(+), 52 deletions(-) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index 8c9caa83..bb171ef9 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -78,12 +78,23 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ govStateResult.setCurrentPParams(currentProtocolParam); // TODO: future protocol params + Array futurePParams = (Array) resultArray.getDataItems().get(5); + if (!futurePParams.getDataItems().isEmpty() && futurePParams.getDataItems().size() > 1) { + List futureParamsDIList = ((Array)futurePParams.getDataItems().get(1)).getDataItems(); + ProtocolParamUpdate futureProtocolParam = deserializePPResult(futureParamsDIList); + govStateResult.setFuturePParams(futureProtocolParam); + } // next ratify state Array nextRatifyStateDI = (Array) ((Array)resultArray.getDataItems().get(6)).getDataItems().get(1); // next ratify state - enacted gov actions - List enactedGovActions = deserializeGovActionIdListResult(nextRatifyStateDI.getDataItems().get(1)); + List enactedProposals = new ArrayList<>(); + Array enactedProposalArr = (Array) nextRatifyStateDI.getDataItems().get(1); + for (var proposalDI : enactedProposalArr.getDataItems()) { + Proposal enactedProposal = deserializeProposalResult(proposalDI); + enactedProposals.add(enactedProposal); + } // next ratify state - expired gov actions List expiredGovActions = deserializeGovActionIdListResult(nextRatifyStateDI.getDataItems().get(2)); @@ -149,7 +160,7 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ .prevGovActionIds(prevGovActionIds) .prevPParams(nextEnactStatePrevPParams) .build()) - .enactedGovActions(enactedGovActions) + .enactedGovActions(enactedProposals) .expiredGovActions(expiredGovActions) .build(); @@ -170,55 +181,8 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ if (item == SimpleValue.BREAK) { continue; } - var proposalDI = (Array) item; - // govActionId - GovActionId govActionId = deserializeGovActionIdResult(proposalDI.getDataItems().get(0)); - // proposalProcedure - var proposalProcedureDI = (Array) proposalDI.getDataItems().get(4); - - ProposalProcedure proposalProcedure = ProposalProcedure.builder() - .anchor(AnchorSerializer.INSTANCE.deserializeDI(proposalProcedureDI.getDataItems().get(3))) - .rewardAccount(HexUtil.encodeHexString(((ByteString) proposalProcedureDI.getDataItems().get(1)).getBytes())) - // TODO: 'govAction' field - .deposit(toBigInteger(proposalProcedureDI.getDataItems().get(0))) - .build(); - - // dRep votes - java.util.Map dRepVotes = new HashMap<>(); - var dRepVotesDI = (Map) proposalDI.getDataItems().get(2); - - for (DataItem key : dRepVotesDI.getKeys()) { - var credentialDI = (Array) key; - int credType = toInt(credentialDI.getDataItems().get(0)); - String credHash = HexUtil.encodeHexString(((ByteString)credentialDI.getDataItems().get(1)).getBytes()); - var voteDI = dRepVotesDI.get(credentialDI); - Vote vote = Vote.values()[toInt(voteDI)]; - dRepVotes.put(credType == 0 ? Drep.addrKeyHash(credHash) : Drep.scriptHash(credHash), vote); - } - - // stake pool votes - java.util.Map stakePoolVotes = new HashMap<>(); - var stakePoolVotesDI = (Map) proposalDI.getDataItems().get(3); - for (DataItem key : stakePoolVotesDI.getKeys()) { - String poolHash = HexUtil.encodeHexString(((ByteString)key).getBytes()); - var voteDI = stakePoolVotesDI.get(key); - Vote vote = Vote.values()[toInt(voteDI)]; - stakePoolVotes.put(StakePoolId.builder().poolKeyHash(poolHash).build(), vote); - } - - // expiredAfter - Integer expiredAfter = toInt(proposalDI.getDataItems().get(6)); - // proposedIn - Integer proposedIn = toInt(proposalDI.getDataItems().get(5)); - proposals.add( - Proposal.builder() - .dRepVotes(dRepVotes) - .stakePoolVotes(stakePoolVotes) - .proposalProcedure(proposalProcedure) - .govActionId(govActionId) - .expiredAfter(expiredAfter) - .proposedIn(proposedIn) - .build()); + Proposal proposal = deserializeProposalResult(item); + proposals.add(proposal); } govStateResult.setProposals(proposals); @@ -554,4 +518,55 @@ public Constitution deserializeConstitutionResult(DataItem constitutionDI) { return Constitution.builder().anchor(anchor).build(); } + public Proposal deserializeProposalResult(DataItem proposalDI) { + Array proposalArray = (Array) proposalDI; + GovActionId govActionId = deserializeGovActionIdResult(proposalArray.getDataItems().get(0)); + + var proposalProcedureDI = (Array) proposalArray.getDataItems().get(4); + + ProposalProcedure proposalProcedure = ProposalProcedure.builder() + .anchor(AnchorSerializer.INSTANCE.deserializeDI(proposalProcedureDI.getDataItems().get(3))) + .rewardAccount(HexUtil.encodeHexString(((ByteString) proposalProcedureDI.getDataItems().get(1)).getBytes())) + // TODO: 'govAction' field + .deposit(toBigInteger(proposalProcedureDI.getDataItems().get(0))) + .build(); + + // dRep votes + java.util.Map dRepVotes = new HashMap<>(); + var dRepVotesDI = (Map) proposalArray.getDataItems().get(2); + + for (DataItem key : dRepVotesDI.getKeys()) { + var credentialDI = (Array) key; + int credType = toInt(credentialDI.getDataItems().get(0)); + String credHash = HexUtil.encodeHexString(((ByteString)credentialDI.getDataItems().get(1)).getBytes()); + var voteDI = dRepVotesDI.get(credentialDI); + Vote vote = Vote.values()[toInt(voteDI)]; + dRepVotes.put(credType == 0 ? Drep.addrKeyHash(credHash) : Drep.scriptHash(credHash), vote); + } + + // stake pool votes + java.util.Map stakePoolVotes = new HashMap<>(); + var stakePoolVotesDI = (Map) proposalArray.getDataItems().get(3); + for (DataItem key : stakePoolVotesDI.getKeys()) { + String poolHash = HexUtil.encodeHexString(((ByteString)key).getBytes()); + var voteDI = stakePoolVotesDI.get(key); + Vote vote = Vote.values()[toInt(voteDI)]; + stakePoolVotes.put(StakePoolId.builder().poolKeyHash(poolHash).build(), vote); + } + + // expiredAfter + Integer expiredAfter = toInt(proposalArray.getDataItems().get(6)); + // proposedIn + Integer proposedIn = toInt(proposalArray.getDataItems().get(5)); + + return Proposal.builder() + .govActionId(govActionId) + .dRepVotes(dRepVotes) + .stakePoolVotes(stakePoolVotes) + .proposalProcedure(proposalProcedure) + .expiredAfter(expiredAfter) + .proposedIn(proposedIn) + .build(); + } + } diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java index 6eff33b6..8fac2e21 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java @@ -11,7 +11,7 @@ @Setter @Builder public class RatifyState { - private List enactedGovActions; + private List enactedGovActions; private List expiredGovActions; private EnactState nextEnactState; private Boolean ratificationDelayed; From 5de50c7cf40cf9a7b36d8505e6ea12cfe276af6c Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 12 Aug 2024 14:19:13 +0700 Subject: [PATCH 08/13] chore: remove 1 todo note in GovStateQuery class --- .../yaci/core/protocol/localstate/queries/GovStateQuery.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index bb171ef9..07a467c5 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -77,7 +77,6 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ govStateResult.setCurrentPParams(currentProtocolParam); - // TODO: future protocol params Array futurePParams = (Array) resultArray.getDataItems().get(5); if (!futurePParams.getDataItems().isEmpty() && futurePParams.getDataItems().size() > 1) { List futureParamsDIList = ((Array)futurePParams.getDataItems().get(1)).getDataItems(); From 09a327c9cd1c8f9f0e8bb7f93dab945a6712a2de Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 12 Aug 2024 16:17:13 +0700 Subject: [PATCH 09/13] chore: (gov state query) update --- .../yaci/core/protocol/localstate/queries/GovStateQuery.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index 07a467c5..4535f96f 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -190,6 +190,10 @@ public GovStateResult deserializeResult(AcceptVersion protocolVersion, DataItem[ } public ProtocolParamUpdate deserializePPResult(List paramsDIList) { + if (paramsDIList.isEmpty()) { + return null; + } + DataItem itemDI = paramsDIList.get(0); Integer minFeeA = itemDI != null ? toInt(itemDI) : null; From 9c0784f81849b3bdf5e9bf84823d8a6a08d3cf37 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 19 Aug 2024 15:32:44 +0700 Subject: [PATCH 10/13] chore: (gov state query) update committee votes --- .../localstate/queries/GovStateQuery.java | 16 ++++++++++++++++ .../localstate/queries/model/Proposal.java | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java index 4535f96f..d09bfdc5 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateQuery.java @@ -534,6 +534,22 @@ public Proposal deserializeProposalResult(DataItem proposalDI) { .deposit(toBigInteger(proposalProcedureDI.getDataItems().get(0))) .build(); + // committee votes + java.util.Map committeeVotes = new HashMap<>(); + var committeeVotesDI = (Map) proposalArray.getDataItems().get(1); + + for (DataItem key : committeeVotesDI.getKeys()) { + var credentialDI = (Array) key; + int credType = toInt(credentialDI.getDataItems().get(0)); + String credHash = HexUtil.encodeHexString(((ByteString) credentialDI.getDataItems().get(1)).getBytes()); + var voteDI = committeeVotesDI.get(credentialDI); + Vote vote = Vote.values()[toInt(voteDI)]; + committeeVotes.put(Credential.builder() + .type(credType == 0 ? StakeCredType.ADDR_KEYHASH : StakeCredType.SCRIPTHASH) + .hash(credHash) + .build(), vote); + } + // dRep votes java.util.Map dRepVotes = new HashMap<>(); var dRepVotesDI = (Map) proposalArray.getDataItems().get(2); diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java index f5b07575..f69d679a 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java @@ -1,5 +1,6 @@ package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; +import com.bloxbean.cardano.yaci.core.model.Credential; import com.bloxbean.cardano.yaci.core.model.certs.StakePoolId; import com.bloxbean.cardano.yaci.core.model.governance.Drep; import com.bloxbean.cardano.yaci.core.model.governance.GovActionId; @@ -16,7 +17,7 @@ @Builder public class Proposal { private GovActionId govActionId; - // TODO: committees votes; + private Map committeeVotes; private Map dRepVotes; private Map stakePoolVotes; private ProposalProcedure proposalProcedure; From bc5cb42a468073549a2f7d21a6bb17f738b9610f Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 19 Aug 2024 18:26:05 +0700 Subject: [PATCH 11/13] chore: update dRep state query --- .../localstate/queries/DRepStateQuery.java | 47 ++++++++++++------- .../localstate/LocalStateQueryAgentIT.java | 16 +++++-- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java index b2009c94..2b8ac432 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQuery.java @@ -6,6 +6,8 @@ import co.nstant.in.cbor.model.Map; import co.nstant.in.cbor.model.UnsignedInteger; import com.bloxbean.cardano.yaci.core.model.Credential; +import com.bloxbean.cardano.yaci.core.model.governance.Anchor; +import com.bloxbean.cardano.yaci.core.model.serializers.governance.AnchorSerializer; import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; @@ -50,23 +52,36 @@ public DRepStateQueryResult deserializeResult(AcceptVersion protocolVersion, Dat var array = (Array) di[0]; var drepStateArray = (Array) array.getDataItems().get(1); - drepStateArray.getDataItems().forEach(dataItem -> { + for (var dataItem : drepStateArray.getDataItems()) { var map = (Map)dataItem; - var key = (List)map.getKeys(); - var itemDI = (Array)key.get(0); - String dRepHash = CborSerializationUtil.toHex(itemDI.getDataItems().get(1)); - var value = (Array) map.get(itemDI); - Integer expiry = CborSerializationUtil.toInt(value.getDataItems().get(0)); - // TODO: anchor - BigInteger deposit = CborSerializationUtil.toBigInteger(value.getDataItems().get(2)); - var dRepState = DRepState.builder() - .dRepHash(dRepHash) - .deposit(deposit) - .expiry(expiry) - .build(); - - result.addDRepState(dRepState); - }); + var keys = (List)map.getKeys(); + + if (keys.isEmpty()) { + continue; + } + for (var key : keys) { + var itemDI = (Array)key; + String dRepHash = CborSerializationUtil.toHex(itemDI.getDataItems().get(1)); + var value = (Array) map.get(itemDI); + Integer expiry = CborSerializationUtil.toInt(value.getDataItems().get(0)); + + Anchor anchor = null; + if (((Array) value.getDataItems().get(1)).getDataItems().size() > 0) { + anchor = AnchorSerializer.INSTANCE.deserializeDI(((Array)value.getDataItems().get(1)).getDataItems().get(0)); + } + + BigInteger deposit = CborSerializationUtil.toBigInteger(value.getDataItems().get(2)); + + var dRepState = DRepState.builder() + .dRepHash(dRepHash) + .anchor(anchor) + .deposit(deposit) + .expiry(expiry) + .build(); + + result.addDRepState(dRepState); + } + } return result; } diff --git a/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java b/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java index 70ed4198..dba57bf4 100644 --- a/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java +++ b/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java @@ -466,10 +466,18 @@ public void acquireFailed(MsgFailure.Reason reason) { @Override public void acquired(Point point) { countDownLatch.countDown(); - localStateQueryAgent.query(new DRepStateQuery(List.of(Credential - .builder() - .type(StakeCredType.ADDR_KEYHASH) - .hash("11b2324445c59782060c4201838c6390bb9d8220cf46538e4f2a73ea").build()))); + localStateQueryAgent.query(new DRepStateQuery(List.of( + Credential + .builder() + .type(StakeCredType.ADDR_KEYHASH) + .hash("5e80b2b80990a738aece6d6068b2991eaea21c52e79c7974719ac275") + .build(), + Credential + .builder() + .type(StakeCredType.ADDR_KEYHASH) + .hash("6e066d1a8bce348956b34438556abb43d597d075f9fdab03bb6f4d39") + .build() + ))); localStateQueryAgent.sendNextMessage(); } From 85db81cb716ea322cd924f0aadd8f8931412a069 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Mon, 19 Aug 2024 18:37:11 +0700 Subject: [PATCH 12/13] chore: add test for gov state query --- .../localstate/LocalStateQueryAgentIT.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java b/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java index dba57bf4..917aaa90 100644 --- a/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java +++ b/core/src/test/java/com/bloxbean/cardano/yaci/core/protocol/localstate/LocalStateQueryAgentIT.java @@ -494,4 +494,55 @@ public void resultReceived(Query query, QueryResult result) { n2CClient.shutdown(); } + + @Test + void govStateQuery_shouldReturn_govState() throws InterruptedException { + HandshakeAgent handshakeAgent = new HandshakeAgent(N2CVersionTableConstant.v1AndAbove(sanchoProtocolMagic)); + LocalStateQueryAgent localStateQueryAgent = new LocalStateQueryAgent(); + + UnixSocketNodeClient n2CClient = new UnixSocketNodeClient(sanchoNodeSocketFile, handshakeAgent, localStateQueryAgent); + + CountDownLatch countDownLatch = new CountDownLatch(2); + handshakeAgent.addListener(new HandshakeAgentListener() { + @Override + public void handshakeOk() { + log.info("HANDSHAKE Successful"); + localStateQueryAgent.acquire(); + localStateQueryAgent.sendNextMessage(); + } + + @Override + public void handshakeError(Reason reason) { + log.info("ERROR {}", reason); + } + }); + + AtomicBoolean failed = new AtomicBoolean(false); + localStateQueryAgent.addListener(new LocalStateQueryListener() { + @Override + public void acquireFailed(MsgFailure.Reason reason) { + countDownLatch.countDown(); + failed.set(true); + } + + @Override + public void acquired(Point point) { + countDownLatch.countDown(); + localStateQueryAgent.query(new GovStateQuery(Era.Conway)); + localStateQueryAgent.sendNextMessage(); + } + + @Override + public void resultReceived(Query query, QueryResult result) { + System.out.println("Query >> " + query); + System.out.println("Result >> " + result); + countDownLatch.countDown(); + } + }); + + n2CClient.start(); + countDownLatch.await(20, TimeUnit.SECONDS); + n2CClient.shutdown(); + } + } From 66f041afc5fe0e8dfafc4c16eaade30c8c73f9d1 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Tue, 20 Aug 2024 09:58:14 +0700 Subject: [PATCH 13/13] chore: remove dRep stake distribution query --- .../queries/DRepStakeDistributionQuery.java | 46 ------------------- .../queries/DRepStakeDistributionResult.java | 7 --- 2 files changed, 53 deletions(-) delete mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java delete mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java deleted file mode 100644 index 62ac398c..00000000 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; - -import co.nstant.in.cbor.model.Array; -import co.nstant.in.cbor.model.DataItem; -import co.nstant.in.cbor.model.UnsignedInteger; -import com.bloxbean.cardano.client.transaction.spec.governance.DRep; -import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; -import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; -import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.ToString; -import lombok.extern.slf4j.Slf4j; - -import java.util.List; - -@Getter -@ToString -@AllArgsConstructor -@Slf4j -public class DRepStakeDistributionQuery implements EraQuery { - private Era era; - private List dReps; - - public DRepStakeDistributionQuery(List dReps) { - this(Era.Conway, dReps); - } - - @Override - public DataItem serialize(AcceptVersion protocolVersion) { - Array array = new Array(); - array.add(new UnsignedInteger(26)); - - Array dRepArray = new Array(); - dReps.forEach(dRep -> dRepArray.add(dRep.serialize())); - - array.add(dRepArray); - - return wrapWithOuterArray(array); - } - - @Override - public DRepStakeDistributionResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { - throw new UnsupportedOperationException("Not implemented yet"); - } -} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java deleted file mode 100644 index 97ac8b35..00000000 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionResult.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; - -import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; - -public class DRepStakeDistributionResult implements QueryResult { - -}