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

Processes withdrawn event #6

Merged
merged 3 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/ProjectOrigin.Chronicler.Server/BlockReader/BlockReaderJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@
{
await ProcessClaimedEvent(repository, transaction);
}
else if (transaction.Header.PayloadType == Electricity.V1.WithdrawnEvent.Descriptor.FullName)
{
await ProcessWithdrawnEvent(repository, transaction);
}
}

await repository.UpsertReadBlock(new LastReadBlock
Expand Down Expand Up @@ -145,7 +149,7 @@
}
else
{
_logger.LogTrace("Allocation for certificate {registry}-{certificateId} not relevant", fid.RegistryName, fid.StreamId);

Check warning on line 152 in src/ProjectOrigin.Chronicler.Server/BlockReader/BlockReaderJob.cs

View workflow job for this annotation

GitHub Actions / analyse / sonar-analysis

Use PascalCase for named placeholders. (https://rules.sonarsource.com/csharp/RSPEC-6678)

Check warning on line 152 in src/ProjectOrigin.Chronicler.Server/BlockReader/BlockReaderJob.cs

View workflow job for this annotation

GitHub Actions / analyse / sonar-analysis

Use PascalCase for named placeholders. (https://rules.sonarsource.com/csharp/RSPEC-6678)
}
}

Expand All @@ -167,13 +171,21 @@
CertificateId = fid.StreamId,
Quantity = claimIntent.Quantity,
RandomR = claimIntent.RandomR,
State = ClaimRecordState.Claimed
});
await repository.DeleteClaimIntent(claimIntent.Id);
await repository.DeleteClaimAllocation(allocation.Id);
}
else
{
_logger.LogTrace("Claim for certificate {registry}-{certificateId} not relevant", fid.RegistryName, fid.StreamId);

Check warning on line 181 in src/ProjectOrigin.Chronicler.Server/BlockReader/BlockReaderJob.cs

View workflow job for this annotation

GitHub Actions / analyse / sonar-analysis

Use PascalCase for named placeholders. (https://rules.sonarsource.com/csharp/RSPEC-6678)

Check warning on line 181 in src/ProjectOrigin.Chronicler.Server/BlockReader/BlockReaderJob.cs

View workflow job for this annotation

GitHub Actions / analyse / sonar-analysis

Use PascalCase for named placeholders. (https://rules.sonarsource.com/csharp/RSPEC-6678)
}
}

private async Task ProcessWithdrawnEvent(IChroniclerRepository repository, Registry.V1.Transaction transaction)

Check warning on line 185 in src/ProjectOrigin.Chronicler.Server/BlockReader/BlockReaderJob.cs

View workflow job for this annotation

GitHub Actions / analyse / sonar-analysis

Make 'ProcessWithdrawnEvent' a static method. (https://rules.sonarsource.com/csharp/RSPEC-2325)

Check warning on line 185 in src/ProjectOrigin.Chronicler.Server/BlockReader/BlockReaderJob.cs

View workflow job for this annotation

GitHub Actions / analyse / sonar-analysis

Make 'ProcessWithdrawnEvent' a static method. (https://rules.sonarsource.com/csharp/RSPEC-2325)
{
var fid = transaction.Header.FederatedStreamId.ToModel();

await repository.WithdrawClaimRecord(fid);
}
}
1 change: 1 addition & 0 deletions src/ProjectOrigin.Chronicler.Server/DatabaseScripts/2.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE claim_records ADD COLUMN state int NOT NULL DEFAULT 0;
7 changes: 7 additions & 0 deletions src/ProjectOrigin.Chronicler.Server/Models/ClaimRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,11 @@ public record ClaimRecord
public required Guid CertificateId { get; init; }
public required long Quantity { get; init; }
public required byte[] RandomR { get; init; }
public required ClaimRecordState State { get; init; }
}

public enum ClaimRecordState
{
Claimed = 0,
Withdrawn = 3
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
<ItemGroup>
<Protobuf Include="../Protos/chronicler.proto" GrpcServices="Both" />
<Protobuf Include="../Protos/registry.proto" Link="Protos\registry.proto">
<SourceUrl>https://raw.githubusercontent.com/project-origin/registry/v1.3.0/src/Protos/registry.proto</SourceUrl>
<SourceUrl>https://raw.githubusercontent.com/project-origin/registry/v2.0.0/protos/registry.proto</SourceUrl>
</Protobuf>
<Protobuf Include="../Protos/electricity.proto" Link="Protos\electricity.proto">
<SourceUrl>https://raw.githubusercontent.com/project-origin/registry/v1.1.0/src/Protos/electricity.proto</SourceUrl>
<SourceUrl>https://raw.githubusercontent.com/project-origin/verifier_electricity/v1.2.0/protos/electricity.proto</SourceUrl>
</Protobuf>
<Protobuf Include="../Protos/common.proto" Link="Protos\common.proto">
<SourceUrl>https://raw.githubusercontent.com/project-origin/registry/v1.3.0/src/Protos/common.proto</SourceUrl>
<SourceUrl>https://raw.githubusercontent.com/project-origin/registry/v2.0.0/protos/common.proto</SourceUrl>
</Protobuf>
</ItemGroup>

Expand Down
12 changes: 12 additions & 0 deletions src/ProjectOrigin.Chronicler.Server/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"profiles": {
"ProjectOrigin.Chronicler.Server": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:50753;http://localhost:50754"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,22 @@ public Task InsertClaimRecord(ClaimRecord record)
VALUES (@id, @registryName, @certificateId, @quantity, @randomR)",
record);
}

public async Task WithdrawClaimRecord(FederatedCertificateId fid)
{
var rowsChanged = await Connection.ExecuteAsync(
@"UPDATE claim_records
SET state = @state
WHERE registry_name = @registryName
AND certificate_id = @certificateId",
new
{
registryName = fid.RegistryName,
certificateId = fid.StreamId,
state = ClaimRecordState.Withdrawn
});

if (rowsChanged != 1)
throw new InvalidOperationException($"ClaimRecord with registry {fid.RegistryName} and certificateId {fid.StreamId} not found");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ public interface IChroniclerRepository
Task DeleteClaimAllocation(Guid id);

Task InsertClaimRecord(ClaimRecord record);
Task WithdrawClaimRecord(FederatedCertificateId fid);

}
34 changes: 34 additions & 0 deletions src/ProjectOrigin.Chronicler.Test/BlockReaderJobTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,27 @@ public async Task Verify_Claimed_NotFound_NotInserted()
_repository.VerifyNoOtherCalls();
}

[Fact]
public async Task ProcessWithdrawnEvent_WithdrawsClaim()
{
// Arrange
var fixture = new Fixture();
var certificateId = new FederatedCertificateId { RegistryName = RegistryName, StreamId = fixture.Create<Guid>() };
var block = new Registry.V1.Block
{
Height = 1,
};
block.AddWithdrawn(certificateId);
_registryService.Setup(x => x.GetNextBlock(RegistryName, 0)).ReturnsAsync(block);

// Act
await _job.ProcessRegistryBlocks(RegistryName, 0, default);

// Assert
_repository.Verify(x => x.UpsertReadBlock(It.Is<LastReadBlock>(x => x.BlockHeight == 1)), Times.Once);
_repository.Verify(x => x.WithdrawClaimRecord(certificateId), Times.Once);
_repository.VerifyNoOtherCalls();
}

[Fact]
public async Task Verify_Claimed_Found_Inserted()
Expand Down Expand Up @@ -454,5 +475,18 @@ public static void AddClaim(this Registry.V1.Block block, Guid allocationId, Fed
}.ToByteString()
});
}

public static void AddWithdrawn(this Registry.V1.Block block, FederatedCertificateId id)
{
block.Transactions.Add(new Registry.V1.Transaction
{
Header = new Registry.V1.TransactionHeader
{
PayloadType = Electricity.V1.WithdrawnEvent.Descriptor.FullName,
FederatedStreamId = id.ToProto(),
},
Payload = new Electricity.V1.WithdrawnEvent().ToByteString()
});
}
}

42 changes: 42 additions & 0 deletions src/ProjectOrigin.Chronicler.Test/ChroniclerRepositoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,4 +376,46 @@ public async Task InsertClaimRecord_InsertsClaimRecord()
// Assert
_con.QuerySingle<ClaimRecord>("SELECT * FROM claim_records").Should().BeEquivalentTo(record);
}

[Fact]
public async Task WithdrawClaimRecord_WithdrawsClaimRecord()
{
var record1 = new ClaimRecord()
{
RegistryName = _fixture.Create<string>(),
State = ClaimRecordState.Claimed,
CertificateId = Guid.NewGuid(),
Id = Guid.NewGuid(),
Quantity = 123,
RandomR = _fixture.Create<byte[]>()
};
var record2 = new ClaimRecord()
{
RegistryName = _fixture.Create<string>(),
State = ClaimRecordState.Claimed,
CertificateId = Guid.NewGuid(),
Id = Guid.NewGuid(),
Quantity = 124,
RandomR = _fixture.Create<byte[]>()
};
await _repository.InsertClaimRecord(record1);
await _repository.InsertClaimRecord(record2);

await _repository.WithdrawClaimRecord(new FederatedCertificateId
{
RegistryName = record1.RegistryName,
StreamId = record1.CertificateId
});

var withdrawnRecord = await _con.QuerySingleAsync<ClaimRecord>(@"SELECT * FROM claim_records
WHERE registry_name = @registryName
AND certificate_id = @certificateId",
new
{
registryName = record1.RegistryName,
certificateId = record1.CertificateId
});

withdrawnRecord.State.Should().Be(ClaimRecordState.Withdrawn);
}
}
8 changes: 8 additions & 0 deletions src/Protos/electricity.proto
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ message ClaimedEvent {
project_origin.common.v1.Uuid allocation_id = 2;
}

message WithdrawnEvent {

}

message UnclaimedEvent {
project_origin.common.v1.Uuid allocation_id = 1;
}

enum GranularCertificateType {
INVALID = 0;
CONSUMPTION = 1;
Expand Down
Loading