Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

805 trigger storage of cah on workstep execution #821

Merged
merged 10 commits into from
Jul 25, 2024
4 changes: 2 additions & 2 deletions .github/workflows/bri-3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ jobs:
DID_REGISTRY: "0x03d5003bf0e79c5f5223588f347eba39afbc3818"
DID_BPI_OPERATOR_PUBLIC_KEY: "0x08872e27BC5d78F1FC4590803369492868A1FCCb"
DID_BPI_OPERATOR_PRIVATE_KEY: "2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58"
CCSM_NETWORK: "sepolia"
CCSM_NETWORK: "localhost"
INFURA_PROVIDER_API_KEY: "c5f37cd25eca4007a9768f18f492bc6f"
CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS: "<smart_contract_address>"
CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS: "0x1CC96ba639d4fd7624913fde39122270a1aC5c34"
SERVICE_URL: "bri-3"
BPI_NATS_SERVER_URL: "localhost:4222"
BPI_NATS_SERVER_USER: "bpi_operator"
Expand Down
4 changes: 2 additions & 2 deletions examples/bri-3/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ DATABASE_URL="postgresql://postgres:example@localhost:5432/postgres" # DB connec
DID_REGISTRY="0x03d5003bf0e79c5f5223588f347eba39afbc3818" # Sepolia did registry https://sepolia.etherscan.io/address/0x03d5003bf0e79c5f5223588f347eba39afbc3818#code
DID_BPI_OPERATOR_PUBLIC_KEY="<bpi_operator_public_key>" # bpi_operator_public_key = public key of the bpi operator that represents the issuer of the JWT token
DID_BPI_OPERATOR_PRIVATE_KEY="<bpi_operator_private_key>" # bpi_operator_private_key = private key of the bpi operator that is used to sign the issued JWT token
CCSM_NETWORK="sepolia" # network used to resolve dids and connect to BPI smart contract
CCSM_NETWORK="localhost" # network used to connect to BPI smart contract
INFURA_PROVIDER_API_KEY="<infura_api_key>" # API key of the infura account used to connect to the network
CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS="<smart_contract_address>" # address of the smart contract where CAHs are stored
CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS="<smart_contract_address>" # address of the smart contract where CAHs are stored (0x1CC96ba639d4fd7624913fde39122270a1aC5c34 for local hardhat node)
SERVICE_URL="bri-3" # JWT token audience
BPI_NATS_SERVER_URL="localhost:4222" # URL of the local NATS server instance used by the BPI
BPI_NATS_SERVER_USER="bpi_operator"
Expand Down
4 changes: 2 additions & 2 deletions examples/bri-3/ccsm/contracts/CcsmBpiStateAnchor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ contract CcsmBpiStateAnchor is AccessControl {
'WorkstepInstanceId cannot be empty'
);
require(
bytes(_workstepInstanceId).length < 36,
'WorkstepInstanceId cannot exceed 36 bytes'
bytes(_workstepInstanceId).length < 40,
'WorkstepInstanceId cannot exceed 40 bytes'
);
require(bytes(_anchorHash).length > 0, 'AnchorHash cannot be empty');
require(
Expand Down
7 changes: 5 additions & 2 deletions examples/bri-3/ccsm/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import { HardhatUserConfig } from 'hardhat/config';
import '@nomicfoundation/hardhat-toolbox';

const config: HardhatUserConfig = {
solidity: '0.8.24',
defaultNetwork: 'hardhat',
solidity: "0.8.24",
defaultNetwork: "localhost",
networks: {
localhost: {
url: "http://127.0.0.1:8545",
},
sepolia: {
url:
'https://sepolia.infura.io/v3/' + process.env.INFURA_PROVIDER_API_KEY,
Expand Down
16 changes: 12 additions & 4 deletions examples/bri-3/ccsm/scripts/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
const hre = require("hardhat");

async function main() {
const [owner, adminAccount] = await hre.ethers.getSigners();
const [originalOwner] = await hre.ethers.getSigners();

const ownerAndAdminPrivateKey = "2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58";
const ownerAndAdmin = new hre.ethers.Wallet(ownerAndAdminPrivateKey, hre.ethers.provider);

await originalOwner.sendTransaction({
to: ownerAndAdmin.address,
value: hre.ethers.parseEther("1.0")
});

const CcsmBpiStateAnchor = await hre.ethers.getContractFactory("CcsmBpiStateAnchor");

const ccsmBpiStateAnchor = await CcsmBpiStateAnchor.deploy([
await owner.getAddress(),
await adminAccount.getAddress(),
const ccsmBpiStateAnchor = await CcsmBpiStateAnchor.connect(ownerAndAdmin).deploy([
ownerAndAdmin.address,
ownerAndAdmin.address,
]);

console.log("CcsmBpiStateAnchor deployed to:", await ccsmBpiStateAnchor.getAddress());
Expand Down
2 changes: 1 addition & 1 deletion examples/bri-3/src/bri/auth/agent/auth.agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export class AuthAgent {
};

const serviceDid =
`did:ethr:${process.env.CCSM_NETWORK}:${process.env.DID_BPI_OPERATOR_PUBLIC_KEY}` as string;
`did:ethr:sepolia:${process.env.DID_BPI_OPERATOR_PUBLIC_KEY}` as string;
const privateKey = process.env.DID_BPI_OPERATOR_PRIVATE_KEY as string;

const serviceSigner = ES256KSigner(hexToBytes(privateKey));
Expand Down
9 changes: 6 additions & 3 deletions examples/bri-3/src/bri/ccsm/agents/ccsmStorage.agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import { ICcsmService } from '../services/ccsm.interface';
@Injectable()
export class CcsmStorageAgent {
constructor(
@Inject('IBlockchainService')
@Inject('ICcsmService')
private readonly ccsmService: ICcsmService,
) {}

async storeAnchorHashOnCcsm(anchorHash: string): Promise<void> {
await this.ccsmService.storeAnchorHash('Ccsm', anchorHash);
async storeAnchorHashOnCcsm(
workstepInstanceId: string,
anchorHash: string,
): Promise<void> {
await this.ccsmService.storeAnchorHash(workstepInstanceId, anchorHash);
}
}
4 changes: 2 additions & 2 deletions examples/bri-3/src/bri/ccsm/ccsm.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { EthereumService } from './services/ethereum.service';
providers: [
CcsmStorageAgent,
{
provide: 'IBlockchainService',
provide: 'ICcsmService',
useClass: EthereumService,
},
],
exports: [CcsmStorageAgent, 'IBlockchainService'],
exports: [CcsmStorageAgent, 'ICcsmService'],
})
export class CcsmModule {}
18 changes: 11 additions & 7 deletions examples/bri-3/src/bri/ccsm/services/ethereum.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Contract,
ethers,
InfuraProvider,
JsonRpcProvider,
Provider,
SigningKey,
} from 'ethers';
Expand All @@ -18,21 +19,24 @@
private wallet: BaseWallet;

constructor() {
// TOOD: This should be environment agnostic, meanning it can worok both against
// local hardhat node, sepolia and mainnet
this.provider = new InfuraProvider(
process.env.CCSM_NETWORK,
process.env.INFURA_PROVIDER_API_KEY,
);
const network = process.env.CCSM_NETWORK;

const signingKey = new SigningKey('0x' + internalBpiSubjectEcdsaPrivateKey);
if (network === 'localhost') {
this.provider = new JsonRpcProvider('http://127.0.0.1:8545');
} else {
this.provider = new InfuraProvider(
network,
process.env.INFURA_PROVIDER_API_KEY,
);
}

const signingKey = new SigningKey(internalBpiSubjectEcdsaPrivateKey);
this.wallet = new BaseWallet(signingKey, this.provider);
}

async connectToContract(): Promise<Contract> {
const ccsmContractAddress =
process.env.CCSM_BPI_STATE_ANCHOR_CONTRACT_ADDRESS!;

Check warning on line 39 in examples/bri-3/src/bri/ccsm/services/ethereum.service.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 17.0.0)

Forbidden non-null assertion

const ccsmBpiStateAnchorContract = new ethers.Contract(
ccsmContractAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import { getResolver } from 'ethr-did-resolver';
import 'dotenv/config';

export class DidService {
// TODO: Hardcoded sepolia everywhere for DID resolution
// This should be taken from the CCSM_NETWORK env value and
// the service refactored to connect to locahost as well,
// with previous deployment of a did registry to local node.
async createKeypair(): Promise<KeyPair> {
const keypair = EthrDID.createKeyPair(process.env.CCSM_NETWORK);
const keypair = EthrDID.createKeyPair('sepolia');
return keypair;
}

async createProvider(): Promise<Provider> {
const provider = new InfuraProvider(
process.env.CCSM_NETWORK,
'sepolia',
process.env.INFURA_PROVIDER_API_KEY,
);
return provider;
Expand All @@ -22,7 +26,7 @@ export class DidService {
const did = new EthrDID({
identifier: process.env.DID_BPI_OPERATOR_PUBLIC_KEY as string,
provider,
chainNameOrId: process.env.CCSM_NETWORK,
chainNameOrId: 'sepolia',
registry: process.env.DID_REGISTRY,
});
return did;
Expand All @@ -31,10 +35,10 @@ export class DidService {
async getDidResolver(provider): Promise<Resolver> {
const didResolver = new Resolver({
...getResolver({
name: process.env.CCSM_NETWORK,
name: 'sepolia',
provider: provider,
registry: process.env.DID_REGISTRY,
chainId: process.env.CCSM_NETWORK,
chainId: 'sepolia',
}),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ export class TransactionStorageAgent {
return this.mapper.map(newTransactionModel, Transaction);
}

async updateTransaction(transaction: Transaction): Promise<Transaction> {
async updateTransactionPayload(
transaction: Transaction,
): Promise<Transaction> {
const updatedTransactionModel = await this.prisma.transaction.update({
where: { id: transaction.id },
data: {
Expand All @@ -143,15 +145,15 @@ export class TransactionStorageAgent {
return this.mapper.map(updatedTransactionModel, Transaction);
}

async updateTransactionStatus(
transaction: Transaction,
): Promise<Transaction> {
async updateTransaction(transaction: Transaction): Promise<Transaction> {
const updatedTransaction = await this.prisma.transaction.update({
where: {
id: transaction.id,
},
data: {
status: transaction.status,
workflowInstanceId: transaction.workflowInstanceId,
workstepInstanceId: transaction.workstepInstanceId,
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,6 @@ export class TransactionAgent {
): Promise<TransactionResult> {
const txResult = new TransactionResult();

//Generate and store workflowInstanceId & workstepInstanceId
const workflowInstanceId = v4();
const workstepInstanceId = v4();

tx.updateWorkflowInstanceId(workflowInstanceId);
tx.updateWorkstepInstanceId(workstepInstanceId);

this.txStorageAgent.updateTransaction(tx);

txResult.merkelizedPayload = this.merkleTreeService.merkelizePayload(
JSON.parse(tx.payload),
`${process.env.MERKLE_TREE_HASH_ALGH}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ describe('TransactionController', () => {
signature: 'signature2',
} as UpdateTransactionDto;

transactionStorageAgentMock.updateTransaction.mockRejectedValueOnce(
transactionStorageAgentMock.updateTransactionPayload.mockRejectedValueOnce(
undefined,
);
// Act and assert
Expand Down Expand Up @@ -285,11 +285,13 @@ describe('TransactionController', () => {
signature: 'signature2',
} as UpdateTransactionDto;

transactionStorageAgentMock.updateTransaction.mockResolvedValueOnce({
...existingTransaction,
payload: updateRequestDto.payload,
signature: updateRequestDto.signature,
} as Transaction);
transactionStorageAgentMock.updateTransactionPayload.mockResolvedValueOnce(
{
...existingTransaction,
payload: updateRequestDto.payload,
signature: updateRequestDto.signature,
} as Transaction,
);

// Act
const updatedTransaction = await controller.updateTransaction(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class UpdateTransactionCommandHandler
command.signature,
);

const updatedTransaction = await this.storageAgent.updateTransaction(
const updatedTransaction = await this.storageAgent.updateTransactionPayload(
transactionToUpdate,
);

Expand Down
10 changes: 3 additions & 7 deletions examples/bri-3/src/bri/transactions/models/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { TransactionStatus } from './transactionStatus.enum';
import { AutoMap } from '@automapper/classes';
import { BpiSubjectAccount } from '../../identity/bpiSubjectAccounts/models/bpiSubjectAccount';
import { InternalServerErrorException } from '@nestjs/common';
import { v4 } from 'uuid';

export class Transaction {
@AutoMap()
Expand Down Expand Up @@ -67,13 +68,6 @@ export class Transaction {
this.status = status;
}

public updateWorkflowInstanceId(workflowInstanceId: string): void {
this.workflowInstanceId = workflowInstanceId;
}

public updateWorkstepInstanceId(workstepInstanceId: string): void {
this.workstepInstanceId = workstepInstanceId;
}
public updatePayload(payload: string, signature: string): void {
// TODO: Verify signature
this.payload = payload;
Expand All @@ -91,6 +85,8 @@ export class Transaction {
}

this.status = TransactionStatus.Processing;
this.workflowInstanceId = v4();
this.workstepInstanceId = v4();
}

public updateStatusToInvalid(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ export class ExecuteVsmCycleCommandHandler
// TODO: When do we update the nonce on the BpiAccount? // Whenever a transaction is initiated
executionCandidates.forEach(async (tx) => {
tx.updateStatusToProcessing();
await this.txStorageAgent.updateTransactionStatus(tx);
await this.txStorageAgent.updateTransaction(tx);

if (!this.txAgent.validateTransactionForExecution(tx)) {
this.eventBus.publish(
new WorkstepExecutedEvent(tx, 'Validation Error'),
);
tx.updateStatusToInvalid();
await this.txStorageAgent.updateTransactionStatus(tx);
await this.txStorageAgent.updateTransaction(tx);
return;
}

Expand All @@ -67,15 +67,17 @@ export class ExecuteVsmCycleCommandHandler
stateTreeRoot,
);

//TODO - Implement deploy and store on CCSM
//await this.ccsmStorageAgent.storeAnchorHashOnCcsm(txResult.hash);
await this.ccsmStorageAgent.storeAnchorHashOnCcsm(
tx.workstepInstanceId,
txResult.hash,
);

tx.updateStatusToExecuted();
this.txStorageAgent.updateTransactionStatus(tx);
this.txStorageAgent.updateTransaction(tx);
} catch (error) {
this.eventBus.publish(new WorkstepExecutedEvent(tx, error));
tx.updateStatusToAborted();
this.txStorageAgent.updateTransactionStatus(tx);
this.txStorageAgent.updateTransaction(tx);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion examples/bri-3/src/bri/vsm/vsm.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const QueryHandlers = [];
useClass: NatsMessagingClient,
},
{
provide: 'IBlockchainService',
provide: 'ICcsmService',
useClass: EthereumService,
},
],
Expand Down
2 changes: 1 addition & 1 deletion examples/bri-3/src/shared/testing/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ export const buyerBpiSubjectEcdsaPrivateKey =
export const internalBpiSubjectEcdsaPublicKey =
'0x08872e27BC5d78F1FC4590803369492868A1FCCb';
export const internalBpiSubjectEcdsaPrivateKey =
'2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58';
'0x2c95d82bcd8851bd3a813c50afafb025228bf8d237e8fd37ba4adba3a7596d58';
Binary file not shown.
Loading