Skip to content

Commit

Permalink
Add events indexing
Browse files Browse the repository at this point in the history
  • Loading branch information
Groxan committed Sep 19, 2022
1 parent 58085ca commit 763515c
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 1 deletion.
1 change: 1 addition & 0 deletions Tzkt.Data/Models/Accounts/Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class Contract : Account
public int CodeHash { get; set; }
public ContractTags Tags { get; set; }
public int TokensCount { get; set; }
public int EventsCount { get; set; }

public bool? Spendable { get; set; }

Expand Down
1 change: 1 addition & 0 deletions Tzkt.Data/Models/AppState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public class AppState
public int TokensCount { get; set; }
public int TokenBalancesCount { get; set; }
public int TokenTransfersCount { get; set; }
public int EventsCount { get; set; }
#endregion

#region quotes
Expand Down
3 changes: 2 additions & 1 deletion Tzkt.Data/Models/Blocks/BlockEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public enum BlockEvents
SmartContracts = 0b_0000_1000_0000,
DelegatorContracts = 0b_0001_0000_0000,
Bigmaps = 0b_0010_0000_0000,
Tokens = 0b_0100_0000_0000
Tokens = 0b_0100_0000_0000,
Events = 0b_1000_0000_0000
}
}
2 changes: 2 additions & 0 deletions Tzkt.Data/Models/Operations/TransactionOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class TransactionOperation : ContractOperation
public short? InternalOriginations { get; set; }
public short? InternalTransactions { get; set; }

public int? EventsCount { get; set; }

#region relations
[ForeignKey(nameof(TargetId))]
public Account Target { get; set; }
Expand Down
60 changes: 60 additions & 0 deletions Tzkt.Data/Models/Scripts/ContractEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Microsoft.EntityFrameworkCore;

namespace Tzkt.Data.Models
{
public class ContractEvent
{
public int Id { get; set; }
public int Level { get; set; }
public int ContractId { get; set; }
public int TransactionId { get; set; }

public string Tag { get; set; }
public byte[] Type { get; set; }
public byte[] RawPayload { get; set; }
public string JsonPayload { get; set; }
}

public static class ContractEventModel
{
public static void BuildContractEventModel(this ModelBuilder modelBuilder)
{
#region keys
modelBuilder.Entity<ContractEvent>()
.HasKey(x => x.Id);
#endregion

#region props
modelBuilder.Entity<ContractEvent>()
.Property(x => x.JsonPayload)
.HasColumnType("jsonb");
#endregion

#region indexes
modelBuilder.Entity<ContractEvent>()
.HasIndex(x => x.Id)
.IsUnique();

modelBuilder.Entity<ContractEvent>()
.HasIndex(x => x.Level);

modelBuilder.Entity<ContractEvent>()
.HasIndex(x => x.ContractId);

modelBuilder.Entity<ContractEvent>()
.HasIndex(x => x.TransactionId);

modelBuilder.Entity<ContractEvent>()
.HasIndex(x => x.Tag);

modelBuilder.Entity<ContractEvent>()
.HasIndex(x => new { x.ContractId, x.Tag });

modelBuilder.Entity<ContractEvent>()
.HasIndex(x => x.JsonPayload)
.HasMethod("gin")
.HasOperators("jsonb_path_ops");
#endregion
}
}
}
4 changes: 4 additions & 0 deletions Tzkt.Data/TzktContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public class TzktContext : DbContext
public DbSet<EndorsingRewardOperation> EndorsingRewardOps { get; set; }
public DbSet<MigrationOperation> MigrationOps { get; set; }
public DbSet<RevelationPenaltyOperation> RevelationPenaltyOps { get; set; }

public DbSet<ContractEvent> Events { get; set; }
#endregion

#region voting
Expand Down Expand Up @@ -154,6 +156,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.BuildEndorsingRewardOperationModel();
modelBuilder.BuildMigrationOperationModel();
modelBuilder.BuildRevelationPenaltyOperationModel();

modelBuilder.BuildContractEventModel();
#endregion

#region voting
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Netezos.Contracts;
using Netezos.Encoding;
using Tzkt.Data.Models;
using Tzkt.Data.Models.Base;

namespace Tzkt.Sync.Protocols.Proto14
{
class ContractEventCommit : ProtocolCommit
{
public ContractEventCommit(ProtocolHandler protocol) : base(protocol) { }

public virtual async Task Apply(Block block, JsonElement content)
{
#region init
var contract = await Cache.Accounts.GetAsync(content.RequiredString("source")) as Contract;
var parentTx = block.Transactions.OrderByDescending(x => x.Id).FirstOrDefault(x => x.Target?.Id == contract.Id)
?? throw new Exception("Event parent transaction not found");

var result = content.Required("result");
if (parentTx.Status != OperationStatus.Applied || result.RequiredString("status") != "applied")
return;

var consumedGas = (int)((result.RequiredInt64("consumed_milligas") + 999) / 1000);

var contractEvent = new ContractEvent
{
Id = Cache.AppState.NextOperationId(),
Level = block.Level,
ContractId = contract.Id,
TransactionId = parentTx.Id,
Tag = content.RequiredString("tag")
};

try
{
var type = Micheline.FromJson(content.Required("type"));
var rawPayload = Micheline.FromJson(content.Required("payload"));
var schema = Schema.Create(type as MichelinePrim);
contractEvent.JsonPayload = schema.Humanize(rawPayload);
contractEvent.RawPayload = schema.Optimize(rawPayload).ToBytes();
contractEvent.Type = type.ToBytes();
}
catch (Exception ex)
{
Logger.LogError(ex, "Failed to process event payload");
}
#endregion

#region apply
parentTx.GasUsed += consumedGas;
parentTx.EventsCount = (parentTx.EventsCount ?? 0) + 1;
contract.EventsCount++;
Cache.AppState.Get().EventsCount++;
block.Events |= BlockEvents.Events;
#endregion

Db.Events.Add(contractEvent);
}

public virtual async Task Revert(Block block)
{
if (!block.Events.HasFlag(BlockEvents.Events))
return;

var events = await Db.Events
.AsNoTracking()
.Where(x => x.Level == block.Level)
.ToListAsync();

foreach (var contractEvent in events)
{
var contract = await Cache.Accounts.GetAsync(contractEvent.ContractId) as Contract;
Db.TryAttach(contract);
contract.EventsCount--;

var state = Cache.AppState.Get();
Db.TryAttach(state);
state.EventsCount--;
}

await Db.Database.ExecuteSqlRawAsync($@"DELETE FROM ""Events"" WHERE ""Level"" = {block.Level};");
}
}
}
4 changes: 4 additions & 0 deletions Tzkt.Sync/Protocols/Handlers/Proto14/Proto14Handler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ public override async Task Commit(JsonElement block)
if (internalTx.BigMapDiffs != null)
bigMapCommit.Append(internalTx.Transaction, internalTx.Transaction.Target as Contract, internalTx.BigMapDiffs);
break;
case "event":
await new ContractEventCommit(this).Apply(blockCommit.Block, internalContent);
break;
default:
throw new NotImplementedException($"internal '{content.RequiredString("kind")}' is not implemented");
}
Expand Down Expand Up @@ -390,6 +393,7 @@ public override async Task Revert()
await new BakingRightsCommit(this).Revert(currBlock);
await new TokensCommit(this).Revert(currBlock);
await new BigMapCommit(this).Revert(currBlock);
await new ContractEventCommit(this).Revert(currBlock);

foreach (var operation in operations.OrderByDescending(x => x.Id))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ protected virtual async Task ValidateTransaction(JsonElement content)
case "delegation": ValidateInternalDelegation(internalContent, source); break;
case "origination": ValidateInternalOrigination(internalContent, source); break;
case "transaction": ValidateInternalTransaction(internalContent, source); break;
case "event": break;
default:
throw new ValidationException("invalid internal operation kind");
}
Expand Down

0 comments on commit 763515c

Please sign in to comment.