1 module tagion.hashgraphview.EventChain; 2 3 version (none) { 4 5 import std.algorithm : map; 6 import std.array : array; 7 import std.range : iota; 8 import tagion.basic.Types : Buffer; 9 import tagion.crypto.SecureInterfaceNet : SecureNet; 10 import tagion.crypto.Types : Pubkey, Signature; 11 import tagion.hashgraph.Event : Event; 12 import tagion.hashgraph.HashGraphBasic : EventBody, EventPackage; 13 import tagion.hibon.Document : Document; 14 import tagion.hibon.HiBON : HiBON; 15 import tagion.hibon.HiBONRecord; 16 import tagion.utils.StdTime : sdt_t; 17 18 enum NIL = -1; // Defines an unconected Event 19 20 @safe 21 struct EventBodyCompact { 22 @label("p") @optional @filter(q{!a.empty}) Document payload; // Transaction 23 @label("m") @filter(q{a != -1}) @fixed(q{-1}) int mother; // Hash of the self-parent 24 @label("f") @filter(q{a != -1}) @fixed(q{-1}) int father; // Hash of the other-parent 25 @label("a") int altitude; 26 @label("t") sdt_t time; 27 @label("M") @optional @(filter.Initialized) Buffer mother_fingerprint; /// This event is connect to the previous mother 28 @label("F") @optional @(filter.Initialized) Buffer father_fingerprint; /// This event is connect to the previous father 29 @label("C") @optional @(filter.Initialized) Pubkey channel; /// Event Channel (Pubkey of the node); 30 mixin HiBONRecord; 31 } 32 33 @safe 34 struct EventCompact { 35 @label("s") Signature signature; // Signature 36 @label("b") EventBodyCompact ebody; // Event Body 37 mixin HiBONRecord; 38 } 39 40 @safe 41 struct EventEpochChunk { 42 @label("epacks") EventCompact[] epacks; 43 @label("chain") Buffer chain; 44 mixin HiBONRecord!( 45 q{ 46 this(EventCompact[] epacks, Buffer chain) pure nothrow { 47 this.epacks=epacks; 48 this.chain=chain; 49 } 50 }); 51 } 52 53 @safe 54 struct HashGraphRecorver { 55 const SecureNet net; 56 this(const SecureNet net) { 57 this.net = net; 58 } 59 60 immutable(EventEpochChunk) opCall(const(Event[]) events, Buffer chain) const pure { 61 int[Buffer] event_ids; 62 foreach (i, e; events) { 63 event_ids[e.fingerprint] = cast(int) i; 64 } 65 EventCompact event_body_compact(const(Event) e) pure { 66 EventBodyCompact ebody; 67 ebody.altitude = e.event_body.altitude; 68 ebody.time = sdt_t(e.event_body.time); 69 ebody.payload = e.event_body.payload; 70 if (e.mother) { 71 ebody.mother = event_ids.get(e.event_body.mother, NIL); 72 if (!(e.event_body.mother in event_ids)) { 73 ebody.mother_fingerprint = e.event_body.mother; 74 ebody.channel = Pubkey(e.channel); 75 } 76 } 77 if (e.father) { 78 ebody.father = event_ids.get(e.event_body.father, NIL); 79 if (!(e.event_body.father in event_ids)) { 80 ebody.father_fingerprint = e.event_body.father; 81 } 82 } 83 EventCompact epack; 84 epack.ebody = ebody; 85 epack.signature = Signature(e.event_package.signature); 86 return epack; 87 } 88 89 auto epacks = 90 events 91 .map!((e) => event_body_compact(e)) 92 .array; 93 return (() @trusted { return cast(immutable) EventEpochChunk(epacks, chain); })(); 94 } 95 96 const(immutable(EventPackage)*[]) opCall(const(EventEpochChunk) epoch_chunk) const { 97 auto result_epacks = new immutable(EventPackage)*[epoch_chunk.epacks.length]; 98 immutable(EventPackage)* reconstruct_epack(const int event_id) { 99 immutable(EventPackage)* result; 100 if (event_id !is NIL) { 101 if (result_epacks[event_id]) { 102 return result_epacks[event_id]; 103 } 104 const ebody_compact = epoch_chunk.epacks[event_id]; 105 Buffer mother_fingerprint; 106 Pubkey channel; 107 if (ebody_compact.ebody.mother_fingerprint) { 108 mother_fingerprint = ebody_compact.ebody.mother_fingerprint; 109 channel = Pubkey(ebody_compact.ebody.channel); 110 } 111 else { 112 const mother = reconstruct_epack(ebody_compact.ebody.mother); 113 mother_fingerprint = mother.fingerprint; 114 channel = Pubkey(mother.pubkey); 115 } 116 Buffer father_fingerprint; 117 if (ebody_compact.ebody.father_fingerprint) { 118 father_fingerprint = ebody_compact.ebody.father_fingerprint; 119 } 120 else { 121 const father = reconstruct_epack(ebody_compact.ebody.father); 122 if (father) { 123 father_fingerprint = father.fingerprint; 124 } 125 } 126 immutable ebody = EventBody( 127 ebody_compact.ebody.payload, 128 mother_fingerprint, 129 father_fingerprint, 130 ebody_compact.ebody.altitude, 131 ebody_compact.ebody.time); 132 133 result = cast(immutable) new EventPackage(net, channel, ebody_compact.signature, ebody); 134 } 135 return result; 136 } 137 // auto result=iota(cast(int)epoch_chunk.epacks.length) 138 // .map!((event_id) => reconstruct_epack(event_id)) 139 // .array; 140 return (() @trusted { 141 return iota(cast(int) epoch_chunk.epacks.length) 142 .map!((event_id) => reconstruct_epack(event_id)) 143 .array; 144 })(); 145 } 146 147 } 148 149 }