Mandatory custodian #44
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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!");
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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,24 +49,29 @@ 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)
|
||||
.getTransaction()
|
||||
.getId();
|
||||
.finalize(this.utxTrxCandidate, sessions)
|
||||
.getTransaction()
|
||||
.getId();
|
||||
|
||||
log.info("GameState commit " +trxId);
|
||||
log.info("GameState commit " + trxId);
|
||||
return trxId;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user