Skip to content

Commit

Permalink
Processes withdrawn event (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
tnickelsen authored Sep 27, 2024
1 parent fa12633 commit 447dfa9
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 3 deletions.
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 @@ private async Task ProcessBlock(IUnitOfWork unitOfWork, string registryName, Reg
{
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 @@ -167,6 +171,7 @@ await repository.InsertClaimRecord(new ClaimRecord
CertificateId = fid.StreamId,
Quantity = claimIntent.Quantity,
RandomR = claimIntent.RandomR,
State = ClaimRecordState.Claimed
});
await repository.DeleteClaimIntent(claimIntent.Id);
await repository.DeleteClaimAllocation(allocation.Id);
Expand All @@ -176,4 +181,11 @@ await repository.InsertClaimRecord(new ClaimRecord
_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

0 comments on commit 447dfa9

Please sign in to comment.