This commit is contained in:
djmil 2023-11-29 12:10:13 +01:00
parent b6b1358131
commit dce7f8e549
11 changed files with 53 additions and 65 deletions

View File

@ -25,8 +25,8 @@ public class GameResultState extends GameState {
this.totalMoves = totalMoves;
}
public GameResultState(MemberX500Name winnerName, GameBoardState gameBoardState, PublicKey custodianPubicKey) {
super(gameBoardState.whitePlayer, gameBoardState.blackPlayer, gameBoardState.gameUuid, null, gameBoardState.participants, custodianPubicKey);
public GameResultState(MemberX500Name winnerName, GameBoardState gameBoardState) {
super(gameBoardState.whitePlayer, gameBoardState.blackPlayer, gameBoardState.gameUuid, null, gameBoardState.participants);
this.winnerName = winnerName;
this.totalMoves = gameBoardState.getMoveNumber();
}

View File

@ -1,7 +1,6 @@
package djmil.cordacheckers.states;
import java.security.PublicKey;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@ -27,18 +26,6 @@ public abstract class GameState implements ContractState {
this.participants = participants;
}
GameState(MemberX500Name whitePlayer, MemberX500Name blackPlayer, UUID gameUuid,
String message, List<PublicKey> participants, PublicKey additionalParticipand) {
this.whitePlayer = whitePlayer;
this.blackPlayer = blackPlayer;
this.gameUuid = gameUuid;
this.message = message;
var deepCopy = new LinkedList<>(participants);
deepCopy.add(additionalParticipand);
this.participants = deepCopy;
}
public MemberX500Name getWhitePlayer() {
return whitePlayer;
}

View File

@ -66,7 +66,7 @@ public class DrawRejectFlow implements ClientStartableFlow{
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitTrx(drawDeclineTrx, currenGameBoardState.getActivePlayerName()));
.subFlow(new CommitTrx(drawDeclineTrx, currenGameBoardState.getParticipants()));
final View gameStateView = this.flowEngine
.subFlow(new ViewBuilder(utxoTrxId));

View File

@ -70,7 +70,7 @@ public class DrawRequestFlow implements ClientStartableFlow{
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitTrx(drawReqTrx, currenGameBoardState.getIdelPlayerName()));
.subFlow(new CommitTrx(drawReqTrx, currenGameBoardState.getParticipants()));
final View gameStateView = this.flowEngine
.subFlow(new ViewBuilder(utxoTrxId));

View File

@ -74,7 +74,7 @@ public class MoveFlow implements ClientStartableFlow{
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitTrx(moveTrx, currenGameBoardState.getIdelPlayerName()));
.subFlow(new CommitTrx(moveTrx, currenGameBoardState.getParticipants()));
if (amIwon(newGameBoard)) {
log.info("Opponent has no possible moves. Claim victory!");

View File

@ -66,7 +66,7 @@ public class AcceptFlow implements ClientStartableFlow{
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitTrx(gameProposalAcceptTrx, gameProposal.getIssuerName()));
.subFlow(new CommitTrx(gameProposalAcceptTrx, gameProposal.getParticipants()));
final View gameView = this.flowEngine
.subFlow(new ViewBuilder(utxoTrxId));

View File

@ -62,7 +62,7 @@ public class CancelFlow implements ClientStartableFlow{
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitTrx(gameProposalCancelTrx, gameProposal.getAcquierName()));
.subFlow(new CommitTrx(gameProposalCancelTrx, gameProposal.getParticipants()));
final View gameStateView = this.flowEngine
.subFlow(new ViewBuilder(utxoTrxId));

View File

@ -59,8 +59,9 @@ public class CreateFlow implements ClientStartableFlow{
try {
final GameCommand command = new GameCommand(GameCommand.Action.GAME_PROPOSAL_CREATE);
final MemberInfo custodianInfo = findCustodian();
final GameProposalState gameProposal = buildGameProposalStateFrom(requestBody);
final GameProposalState gameProposal = buildGameProposalStateFrom(requestBody, custodianInfo);
final UtxoSignedTransaction gameProposalCreateTrx = utxoLedgerService.createTransactionBuilder()
.addCommand(command)
@ -71,7 +72,7 @@ public class CreateFlow implements ClientStartableFlow{
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitTrx(gameProposalCreateTrx, gameProposal.getAcquierName()));
.subFlow(new CommitTrx(gameProposalCreateTrx, gameProposal.getParticipants()));
final View gameView = this.flowEngine
.subFlow(new ViewBuilder(utxoTrxId));
@ -87,7 +88,7 @@ public class CreateFlow implements ClientStartableFlow{
}
@Suspendable
GameProposalState buildGameProposalStateFrom(ClientRequestBody requestBody) {
GameProposalState buildGameProposalStateFrom(ClientRequestBody requestBody, MemberInfo custodianInfo) {
final CreateFlowArgs args = requestBody.getRequestBodyAs(jsonMarshallingService, CreateFlowArgs.class);
final MemberInfo myInfo = memberLookup.myInfo();
@ -108,7 +109,9 @@ public class CreateFlow implements ClientStartableFlow{
args.message,
Arrays.asList(
myInfo.getLedgerKeys().get(0),
opponentInfo.getLedgerKeys().get(0))
opponentInfo.getLedgerKeys().get(0),
custodianInfo.getLedgerKeys().get(0)
)
);
}
@ -121,4 +124,12 @@ public class CreateFlow implements ClientStartableFlow{
.orElseThrow( () -> new IllegalStateException("No Notary VNode found"));
}
@Suspendable
MemberInfo findCustodian() {
return memberLookup.lookup()
.stream()
.filter(member -> VNode.isCordaCherckersCustodian(member) )
.reduce((a,b) -> {throw new IllegalStateException("Multiple Custodian VNodes");})
.orElseThrow( () -> new IllegalStateException("No Custodian VNode found"));
}
}

View File

@ -70,7 +70,7 @@ public class RejectFlow implements ClientStartableFlow{
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitTrx(gameProposalRejectTrx, gameProposal.getIssuerName()));
.subFlow(new CommitTrx(gameProposalRejectTrx, gameProposal.getParticipants()));
final View gameStateView = this.flowEngine
.subFlow(new ViewBuilder(utxoTrxId));

View File

@ -1,6 +1,5 @@
package djmil.cordacheckers.gameresult;
import java.security.PublicKey;
import java.time.Duration;
import java.time.Instant;
import java.util.UUID;
@ -46,13 +45,12 @@ public class GameResultCommiter implements SubFlow<SecureHash> {
@Override
@Suspendable
public SecureHash call() {
final MemberInfo custodianInfo = findCustodian();
final StateAndRef<GameState> gameBoardSar = this.flowEngine
.subFlow(new GetFlow(this.gameUuid));
final GameBoardState gameBoard = (GameBoardState)gameBoardSar.getState().getContractState();
final GameResultState gameResult = gameResultBuilder(gameBoard, custodianInfo);
final GameResultState gameResult = gameResultBuilder(gameBoard);
final UtxoSignedTransaction gameResultTrx = utxoLedgerService.createTransactionBuilder()
.addCommand(this.command)
@ -64,9 +62,7 @@ public class GameResultCommiter implements SubFlow<SecureHash> {
.toSignedTransaction();
return this.flowEngine.subFlow(
new CommitTrx(gameResultTrx,
getCounterparty(gameResult),
custodianInfo.getName()) );
new CommitTrx(gameResultTrx, gameResult.getParticipants()));
}
@Suspendable
@ -79,32 +75,25 @@ public class GameResultCommiter implements SubFlow<SecureHash> {
}
@Suspendable
GameResultState gameResultBuilder(GameBoardState gameBoard, MemberInfo custodiaInfo) {
final PublicKey custodianPublicKey = custodiaInfo.getLedgerKeys().get(0);
GameResultState gameResultBuilder(GameBoardState gameBoard) {
final MemberX500Name myName = memberLookup.myInfo().getName();
switch(this.command.getAction()) {
case CLAIM_VICTORY:
return new GameResultState(myName, // i'm a winner
gameBoard, custodianPublicKey);
gameBoard);
case SURRENDER:
return new GameResultState(gameBoard.getOpponentName(myName), // me surrender to opponent
gameBoard, custodianPublicKey);
gameBoard);
case DRAW_ACCEPT:
return new GameResultState(null, // there is no winner, it's a draw
gameBoard, custodianPublicKey);
gameBoard);
default:
throw new IllegalStateException("GameResult: bad reason");
}
}
@Suspendable
MemberX500Name getCounterparty(GameState gameState) {
final MemberX500Name myName = this.memberLookup.myInfo().getName();
return gameState.getOpponentName(myName);
}
}

View File

@ -1,5 +1,6 @@
package djmil.cordacheckers.gamestate;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@ -19,24 +20,19 @@ import net.corda.v5.crypto.SecureHash;
import net.corda.v5.ledger.utxo.UtxoLedgerService;
import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction;
import static java.util.Objects.*;
import static java.util.stream.Collectors.toList;
@InitiatingFlow(protocol = "gamestate-commit")
public class CommitTrx implements SubFlow<SecureHash> {
private final static Logger log = LoggerFactory.getLogger(CommitTrx.class);
private final UtxoSignedTransaction utxTrxCandidate;
private final MemberX500Name counterpartyName;
private final MemberX500Name custodyName;
private final List<PublicKey> participants;
public CommitTrx(UtxoSignedTransaction signedTransaction, MemberX500Name counterpartyName) {
public CommitTrx(UtxoSignedTransaction signedTransaction, List<PublicKey> participants) {
this.utxTrxCandidate = signedTransaction;
this.counterpartyName = counterpartyName;
this.custodyName = null;
}
public CommitTrx(UtxoSignedTransaction signedTransaction, MemberX500Name counterpartyName, MemberX500Name custodyName) {
this.utxTrxCandidate = signedTransaction;
this.counterpartyName = counterpartyName;
this.custodyName = custodyName;
this.participants = participants;
}
@CordaInject
@ -53,20 +49,25 @@ public class CommitTrx implements SubFlow<SecureHash> {
public SecureHash call() {
log.info("GameState commit started");
final MemberX500Name myName = memberLookup.myInfo().getName();
List<FlowSession> sessions = participants.stream()
.map(pubKey -> requireNonNull(memberLookup.lookup(pubKey), "Member not found from public Key " + pubKey + ".").getName())
.filter(person -> person.compareTo(myName) != 0)
.map(signatorieX500name -> flowMessaging.initiateFlow(signatorieX500name))
.collect(toList());
if (sessions.size() != 2)
throw new RuntimeException("Should be strictly TWO signatories other than the initiator");
/*
* Calls the Corda provided finalise() function which gather signatures from the counterparty,
* Calls the Corda provided finalise() function which gather signatures from the
* counterparty,
* notarises the transaction and persists the transaction to each party's vault.
*/
final FlowSession session = flowMessaging.initiateFlow(this.counterpartyName);
List<FlowSession> sessionsList = new LinkedList<FlowSession>(Arrays.asList(session));
if (custodyName != null) {
sessionsList.add(flowMessaging.initiateFlow(custodyName));
}
final SecureHash trxId = ledgerService
.finalize(this.utxTrxCandidate, sessionsList)
.finalize(this.utxTrxCandidate, sessions)
.getTransaction()
.getId();