diff --git a/Server version/Blackbox/Util/Docu/Sets.odc b/Server version/Blackbox/Util/Docu/Sets.odc index 6bc8de0..62ad37e 100644 Binary files a/Server version/Blackbox/Util/Docu/Sets.odc and b/Server version/Blackbox/Util/Docu/Sets.odc differ diff --git a/Server version/Blackbox/Util/Mod/Sets.odc b/Server version/Blackbox/Util/Mod/Sets.odc index e40c60d..34eb438 100644 Binary files a/Server version/Blackbox/Util/Mod/Sets.odc and b/Server version/Blackbox/Util/Mod/Sets.odc differ diff --git a/Server version/Documentation/Util/Sets.txt b/Server version/Documentation/Util/Sets.txt index 6215352..5b6f247 100644 --- a/Server version/Documentation/Util/Sets.txt +++ b/Server version/Documentation/Util/Sets.txt @@ -22,18 +22,21 @@ DEFINITION UtilSets; (s1: Set) Diff (s2: Set): Set, NEW; (s1: Set) XOR (s2: Set): Set, NEW; (s: Set) In (e: INTEGER): BOOLEAN, NEW; - (s: Set) NbOfElems (): INTEGER, NEW; (s: Set) IsEmpty (): BOOLEAN, NEW; (s1: Set) Equal (s2: Set): BOOLEAN, NEW; (s1: Set) Subset (s2: Set): BOOLEAN, NEW; (s: Set) NextElem (inc: BOOLEAN; VAR e: INTEGER): BOOLEAN, NEW; - (s: Set) FirstE (OUT e: INTEGER): BOOLEAN, NEW; - (s: Set) NextE (OUT e: INTEGER): BOOLEAN, NEW; - (s: Set) First (OUT min, max: INTEGER): BOOLEAN, NEW; - (s: Set) Next (OUT min, max: INTEGER): BOOLEAN, NEW; (s: Set) Copy (): Set, NEW END; + SetIterator = RECORD + (VAR i: SetIterator) Attach (s: Set), NEW; + (VAR i: SetIterator) First (OUT min, max: INTEGER): BOOLEAN, NEW; + (VAR i: SetIterator) Next (OUT min, max: INTEGER): BOOLEAN, NEW; + (VAR i: SetIterator) FirstE (OUT e: INTEGER): BOOLEAN, NEW; + (VAR i: SetIterator) NextE (OUT e: INTEGER): BOOLEAN, NEW + END; + PROCEDURE NewSet (): Set; END UtilSets. @@ -54,113 +57,127 @@ Number of elements in the set. PROCEDURE (s: Set) Empty NEW -Empties the set s. +Empty the set s. PROCEDURE (s: Set) Full NEW -Returns in s the largest set available: sMin..sMax. +Returnsin s the largest set available: sMin..sMax. PROCEDURE (s: Set) Interval (min, max: INTEGER) NEW -Sets s to the interval min..max. +Set s to the interval min..max. Pre min..max is included in sMin..sMax 20 PROCEDURE (s: Set) Clear (min, max: INTEGER) NEW -Removes the interval min..max from the set s. +Remove the interval min..max from the set s. PROCEDURE (s: Set) Fill (min, max: INTEGER) NEW -Adds the interval min..max to the set s. +Add the interval min..max to the set s. PROCEDURE (s: Set) Incl (e: INTEGER) NEW -Includes the integer e in the set s. +Include the integer e in the set s. PROCEDURE (s: Set) Excl (e: INTEGER) NEW -Excludes the integer e from the set s. +Exclude the integer e from the set s. PROCEDURE (s: Set) Small (se: SET) NEW -Sets s to the Component Pascal SET se. +Set s to the Component Pascal SET se. PROCEDURE (s1: Set) Union (s2: Set): Set NEW -Returns the union of s1 and s2. +Return the union of s1 and s2. Pre s2 # NIL 20 PROCEDURE (s1: Set) Inter (s2: Set): Set NEW -Returns the intersection of s1 and s2. +Return the intersection of s1 and s2. Pre s2 # NIL 20 PROCEDURE (s1: Set) Diff (s2: Set): Set NEW -Returns the difference between s1 and s2. +Return the difference between s1 and s2. Pre s2 # NIL 20 PROCEDURE (s1: Set) XOR (s2: Set): Set NEW -Returns the exclusive union of s1 and s2. +Return the exclusive union of s1 and s2. Pre s2 # NIL 20 PROCEDURE (s: Set) In (e: INTEGER): BOOLEAN NEW -Tests whether the integer e is in the set s. - -PROCEDURE (s: Set) NbOfElems (): INTEGER -NEW -Returns the number of elements in s. +Check whether the integer e is in the set s. PROCEDURE (s: Set) IsEmpty (): BOOLEAN NEW -Tests whether s is empty. +Check whether s is empty. PROCEDURE (s1: Set) Equal (s2: Set): BOOLEAN NEW -Tests whether s1 = s2. +Check whether s1 = s2. PROCEDURE (s1: Set) Subset (s2: Set): BOOLEAN NEW -Tests whether s1 is a subset (in the broad sense of the word) of s2. +Check whether s1 is a subset (in the broad sense of the word) of s2. PROCEDURE (s: Set) NextElem (inc: BOOLEAN; VAR e: INTEGER): BOOLEAN NEW -Replaces e by the next integer e' of s. If inc = TRUE, e' > e; otherwise, e' < e. e may be outside of the interval sMin..sMax, but e' is inside it. Returns TRUE if there is such a successor of e, otherwise e is unchanged. Usage: e := sMin - 1; WHILE s.NextElem(TRUE, e) DO ... END; +Replace e by the next integer e' of s. If inc = TRUE, e' > e; otherwise, e' < e. e may be outside of the interval sMin..sMax, but e' is inside it. Return TRUE if there is such a successor of e, otherwise e is unchanged. Usage: e := sMin - 1; WHILE s.NextElem(TRUE, e) DO ... END; -PROCEDURE (s: Set) FirstE (OUT e: INTEGER): BOOLEAN +PROCEDURE (s: Set) Copy (): Set NEW -On return, e contains the first integer of the set s. Returns TRUE if such an integer exists. Usage: ok := s.FirstE(e); WHILE ok DO ... ok := s.NextE(e) END;. Using FirstE & NextE works faster than using NextElem. +Create and return a copy of s. + +TYPE SetIterator +Iterator of a Set.. + +PROCEDURE (VAR i: SetIterator) Attach (s: Set), NEW; +Attach the set s to i.. -PROCEDURE (s: Set) NextE (OUT e: INTEGER): BOOLEAN +PROCEDURE (VAR i: SetIterator) First (OUT min, max: INTEGER): BOOLEAN NEW -On return, e contains the next integer of the set s. Returns TRUE if such an integer exists. s.FirstE must have been called once before s.NextE. Usage: ok := s.FirstE(e); WHILE ok DO ... ok := s.NextE(e) END;. Using FirstE & NextE works faster than using NextElem. +On return, min and max contain the first interval of the set attached to i. Return TRUE if such an interval exists. Usage: ok := i.First(a, b); WHILE ok DO ... ok := s.Next(a, b) END; -PROCEDURE (s: Set) First (OUT min, max: INTEGER): BOOLEAN +Pre +i has been attached to a Set 20 +i.First was called once before 21 + +PROCEDURE (VAR i: SetIterator) Next (OUT min, max: INTEGER): BOOLEAN NEW -On return, min and max contain the first interval of the set s. Returns TRUE if such an interval exists. Usage: ok := s.First(a, b); WHILE ok DO ... ok := s.Next(a, b) END; +On return, min and max contain the next interval of the set attached to i. Returns TRUE if such an interval exists. i.First must have been called once before i.Next. Usage: ok := i.First(a, b); WHILE ok DO ... ok := i.Next(a, b) END; + +Pre +i has been attached to a Set 20 +i.First was called once before 21 -PROCEDURE (s: Set) Next (OUT min, max: INTEGER): BOOLEAN +PROCEDURE (VAR i: SetIterator) FirstE (OUT e: INTEGER): BOOLEAN NEW -On return, min and max contain the next interval of the set s. Returns TRUE if such an interval exists. s.First must have been called once before s.Next. Usage: ok := s.First(a, b); WHILE ok DO ... ok := s.Next(a, b) END; +On return, e contains the first integer of the set attached to i. Return TRUE if such an integer exists. Usage: ok := i.FirstE(e); WHILE ok DO ... ok := i.NextE(e) END;. Using FirstE & NextE works faster than using NextElem. Pre -s.First was called once before 20 +i has been attached to a Set 20 -PROCEDURE (s: Set) Copy (): Set +PROCEDURE (VAR i: SetIterator) NextE (OUT e: INTEGER): BOOLEAN NEW -Creates and returns a copy of s. +On return, e contains the next integer of the set attached to i. Return TRUE if such an integer exists. i.FirstE must have been called once before i.NextE. Usage: ok := i.FirstE(e); WHILE ok DO ... ok := i.NextE(e) END;. Using FirstE & NextE works faster than using NextElem. + +Pre +i has been attached to a Set 20 +i.First was called once before 21 PROCEDURE NewSet (): Set Creates and returns a new empty set. \ No newline at end of file diff --git a/Server version/Sources/Duniter/Blockchain.txt b/Server version/Sources/Duniter/Blockchain.txt index e27b770..c95d22f 100644 --- a/Server version/Sources/Duniter/Blockchain.txt +++ b/Server version/Sources/Duniter/Blockchain.txt @@ -63,8 +63,6 @@ MODULE DuniterBlockchain; TYPE - IsFree* = PROCEDURE (IN p: Pubkey): BOOLEAN; - UpdateProc* = PROCEDURE; (* Procedure called at every update *) UpdateList = POINTER TO RECORD (* Chained list of procedures called at every update *) @@ -264,8 +262,6 @@ MODULE DuniterBlockchain; VAR - isFree: IsFree; - duniBase-: Files.Name; (* Path to the Duniter database *) updateList: UpdateList; (* Head of UpdateList *) @@ -286,6 +282,7 @@ MODULE DuniterBlockchain; (* Sentries & Distance Rule *) members: MembersFind; sentriesS: U.Set; (* Set of sentries *) + sentriesI:U.SetIterator; (* Iterator of sentriesS *) poST: A.Tree; undoList: INTEGER; (* Head of UndoList *) @@ -1333,9 +1330,9 @@ MODULE DuniterBlockchain; BEGIN (*NextSentry*) IF first THEN - b := sentriesS.FirstE(sentryCur); + b := sentriesI.FirstE(sentryCur); ELSE - b := sentriesS.NextE(sentryCur); + b := sentriesI.NextE(sentryCur); END; IF ~b THEN RETURN FALSE; @@ -1348,7 +1345,7 @@ MODULE DuniterBlockchain; PROCEDURE SentriesLen* (): INTEGER; BEGIN (*SentriesLen*) - RETURN sentriesS.NbOfElems(); + RETURN sentriesS.nbElems; END SentriesLen; (* Array of certifiers' pubkeys -> % of sentries reached in pars.stepMax - 1 steps *) @@ -1357,11 +1354,11 @@ MODULE DuniterBlockchain; VAR set, frontier, newFrontier: U.Set; + frontierI: U.SetIterator; e, i: INTEGER; ok: BOOLEAN; poS: REAL; poSE: PoSE; - ee: A.Elem; PROCEDURE Sort (pubkeys: Pubkeys); @@ -1382,37 +1379,41 @@ MODULE DuniterBlockchain; END; END Sort; - PROCEDURE Find (pubkeys: Pubkeys; OUT poS: REAL): BOOLEAN; + PROCEDURE Find (poSE: PoSE; OUT poS: REAL): BOOLEAN; VAR n: INTEGER; + e: A.Elem; BEGIN (*Find*) - IF ~poST.Search(ee, n) THEN + e := poSE; + IF ~poST.Search(e, n) THEN RETURN FALSE; END; - poS := ee(PoSE).poS; + poS := e(PoSE).poS; RETURN TRUE; END Find; - PROCEDURE Store (pubkeys: Pubkeys; poS: REAL); + PROCEDURE Store (poSE: PoSE; poS: REAL); VAR b: BOOLEAN; n: INTEGER; + e: A.Elem; BEGIN (*Store*) poSE.poS := poS; - b := poST.SearchIns(ee, n); ASSERT(~b, 100); + e := poSE; + b := poST.SearchIns(e, n); ASSERT(~b, 100); END Store; BEGIN (*PercentOfSentries*) Sort(pubkeys); - NEW(poSE); ee := poSE; + NEW(poSE); poSE.pubkeys := pubkeys; - IF ~Find(pubkeys, poS) THEN + IF ~Find(poSE, poS) THEN set := U.NewSet(); frontier := U.NewSet(); FOR i := 0 TO LEN(pubkeys) - 1 DO @@ -1423,16 +1424,17 @@ MODULE DuniterBlockchain; END; FOR i := 1 TO pars.stepMax - 1 DO newFrontier := U.NewSet(); - ok := frontier.FirstE(e); + frontierI.Attach(frontier); + ok := frontierI.FirstE(e); WHILE ok DO newFrontier := newFrontier.Union(members.m[e].links); - ok := frontier.NextE(e); + ok := frontierI.NextE(e); END; frontier := newFrontier; set := set.Union(frontier); END; - poS := set.Inter(sentriesS).NbOfElems() / sentriesS.NbOfElems(); - Store(pubkeys, poS); + poS := set.Inter(sentriesS).nbElems / sentriesS.nbElems; + Store(poSE, poS); END; RETURN poS; END PercentOfSentries; @@ -1551,37 +1553,6 @@ MODULE DuniterBlockchain; rNow := MAX(rNow, t.time); END Times; - PROCEDURE RemoveId (withList: BOOLEAN; p: Pubkey); - - VAR - - idP: PubKey; - b: BOOLEAN; - idRef: INTEGER; - id: Identity; - idU: B.String; - idL: UndoList; (* removeIdList *) - - BEGIN (*RemoveId*) - NEW(idP); idP.ref := p; - IF ~certFromT.Search(idP) & ~certToT.Search(idP) & isFree(p) THEN - b := idPubT.Search(idP); ASSERT(b, 100); - idRef := idPubT.ReadValue(); - id := idMan.ReadData(idRef)(Identity); - IF id.expires_on # BA.revoked THEN - b := idPubT.Erase(idP); ASSERT(b, 101); - NEW(idU); idU.c := id.uid; - b := idUidT.Erase(idU); ASSERT(b, 102); - IF withList THEN - NEW(idL); idL.next := undoList; idL.type := removeIdList; idL.ref := idRef; idL.aux := 0; - undoList := undoListMan.WriteAllocateData(idL); - ELSE - idMan.EraseData(idRef); - END; - END; - END; - END RemoveId; - (* For one block, add joining & leaving identities in joinAndLeaveT and updade identities in idPubT and idUidT; update certFromT & certToT too *) PROCEDURE Identities (withList: BOOLEAN; IN ssJ, ssA, ssL, ssR, ssE, nb: ARRAY OF CHAR; t: S.Table); @@ -1594,7 +1565,7 @@ MODULE DuniterBlockchain; id, oldId: Identity; idP: PubKey; idU: B.String; - idL: UndoList; (* addIdList, joinList, activeList, leaveList *) + idL: UndoList; (* joinList, activeList *) jl: JoinAndLeave; jlL: JoinAndLeaveL; cur: S.Row; @@ -1705,7 +1676,7 @@ MODULE DuniterBlockchain; END; i := 1; - WHILE ssL[i] # ']' DO (* leavers : Remove id *) + WHILE ssL[i] # ']' DO (* leavers *) INC(i); NEW(idP); ScanS(ssL, ':', idP.ref, i); @@ -1725,7 +1696,7 @@ MODULE DuniterBlockchain; END; i := 1; - WHILE ssR[i] # ']' DO (* revoked : Remove id *) + WHILE ssR[i] # ']' DO (* revoked *) INC(i); NEW(idP); ScanS(ssR, ':', idP.ref, i); @@ -1740,12 +1711,12 @@ MODULE DuniterBlockchain; NEW(idL); idL.next := undoList; idL.type := activeList; idL.ref := idRef; idL.aux := id.expires_on; undoList := undoListMan.WriteAllocateData(idL); END; - id.expires_on := BA.revoked; (* BA.revoked? pour ne pas l'effacer ? *) + id.expires_on := BA.revoked; idMan.WriteData(idRef, id); END; i := 1; - WHILE ssE[i] # ']' DO (* excluded : Remove id *) + WHILE ssE[i] # ']' DO (* excluded *) INC(i); DEC(idLenM); NEW(idP); @@ -1770,22 +1741,17 @@ MODULE DuniterBlockchain; NEW(idL); idL.next := undoList; idL.type := leaveList; idL.ref := idRef; idL.aux := 0; undoList := undoListMan.WriteAllocateData(idL); END; - IF id.expires_on = BA.missing THEN - RemoveId(withList, idP.ref); - ELSIF id.expires_on # BA.revoked THEN + IF (id.expires_on # BA.missing) & (id.expires_on # BA.revoked) THEN IF withList THEN NEW(idL); idL.next := undoList; idL.type := activeList; idL.ref := idRef; idL.aux := id.expires_on; undoList := undoListMan.WriteAllocateData(idL); END; INC(id.expires_on, pars.msValidity); idMan.WriteData(idRef, id); - IF ~certFromT.Search(idP) & ~certToT.Search(idP) & isFree(idP.ref) THEN - NEW(iK); iK.ref := idRef; - b := idTimeT.SearchIns(iK); ASSERT(~b, 121); - END; + NEW(iK); iK.ref := idRef; + b := idTimeT.SearchIns(iK); ASSERT(~b, 121); END; END; - database.WritePlace(idLenPlace, idLenM); END Identities; (* Add certificatoins of one block in certFromT, certToT and certTimeT *) @@ -1921,12 +1887,33 @@ MODULE DuniterBlockchain; ELSE certMan.EraseData(pC); END; - RemoveId(withList, c.from); - RemoveId(withList, c.to); END; END RemoveExpiredCerts; - PROCEDURE RemoveExpiredIds (now, secureNow: LONGINT); + PROCEDURE RevokeId (withList: BOOLEAN; p: Pubkey); + + VAR + + idP: PubKey; + b: BOOLEAN; + idRef: INTEGER; + id: Identity; + idL: UndoList; (* leaversList *) + + BEGIN (*RevokeId*) + NEW(idP); idP.ref := p; + b := idPubT.Search(idP); ASSERT(b, 100); + idRef := idPubT.ReadValue(); + id := idMan.ReadData(idRef)(Identity); + IF withList THEN + NEW(idL); idL.next := undoList; idL.type := activeList; idL.ref := idRef; idL.aux := id.expires_on; + undoList := undoListMan.WriteAllocateData(idL); + END; + id.expires_on := BA.revoked; + idMan.WriteData(idRef, id); + END RevokeId; + + PROCEDURE RevokeExpiredIds (now, secureNow: LONGINT); VAR @@ -1935,7 +1922,7 @@ MODULE DuniterBlockchain; b, withList: BOOLEAN; pId: INTEGER; - BEGIN (*RemoveExpiredIds*) + BEGIN (*RevokeExpiredIds*) NEW(id); id.expires_on := now; id.pubkey := ""; NEW(id.uid, 1); id.uid^ := ""; pId := idMan.WriteAllocateData(id); NEW(iK); iK.ref := pId; @@ -1948,9 +1935,9 @@ MODULE DuniterBlockchain; iK.ref := pId; b := idTimeT.Erase(iK); ASSERT(b, 100); withList := id.expires_on >= secureNow; - RemoveId(withList, id.pubkey); + RevokeId(withList, id.pubkey); END; - END RemoveExpiredIds; + END RevokeExpiredIds; (* Undo the last operations done from the secureGap last blocks *) PROCEDURE RemoveSecureGap; @@ -2030,16 +2017,11 @@ MODULE DuniterBlockchain; idMan.WriteData(l.ref, id); INC(idLenM); NEW(p); p.ref := id.pubkey; - b := idPubT.SearchIns(p); ASSERT(~b, 108); - idPubT.WriteValue(l.ref); - NEW(u); u.c := id.uid; - b := idUidT.SearchIns(u); ASSERT(~b, 109); - idUidT.WriteValue(l.ref); - b := joinAndLeaveT.Search(p); ASSERT(b, 110); + b := joinAndLeaveT.Search(p); ASSERT(b, 108); jlRef := joinAndLeaveT.ReadValue(); jl := joinAndLeaveMan.ReadData(jlRef)(JoinAndLeave); jlL := joinAndLeaveLMan.ReadData(jl.list)(JoinAndLeaveL); - ASSERT(jlL.leavingBlock # hasNotLeaved, 111); + ASSERT(jlL.leavingBlock # hasNotLeaved, 109); jlL.leavingBlock := hasNotLeaved; joinAndLeaveLMan.WriteData(jl.list, jlL); |certAddList: @@ -2047,7 +2029,7 @@ MODULE DuniterBlockchain; c := certMan.ReadData(l.ref)(Certification); RemoveCert(c); NEW(i); i.ref := l.ref; - b := certTimeT.Erase(i); ASSERT(b, 112); + b := certTimeT.Erase(i); ASSERT(b, 110); certMan.EraseData(l.ref); |certRemoveList: (* Insert the keys corresponding to the Certification pointed by l.ref into certFromT, certToT and certTimeT *) @@ -2062,7 +2044,7 @@ MODULE DuniterBlockchain; END; p.ref := c.to; ind := database.OpenIndex(n, pubKeyMan, pubKeyFac); - b := ind.SearchIns(p); ASSERT(~b, 113); + b := ind.SearchIns(p); ASSERT(~b, 111); ind.WriteValue(l.ref); ind.Close; IF certToT.SearchIns(p) THEN @@ -2073,11 +2055,11 @@ MODULE DuniterBlockchain; END; p.ref := c.from; ind := database.OpenIndex(n, pubKeyMan, pubKeyFac); - b := ind.SearchIns(p); ASSERT(~b, 114); + b := ind.SearchIns(p); ASSERT(~b, 113); ind.WriteValue(l.ref); ind.Close; NEW(i); i.ref := l.ref; - b := certTimeT.SearchIns(i); ASSERT(~b, 115); + b := certTimeT.SearchIns(i); ASSERT(~b, 114); END; undoListMan.EraseData(undoList); undoList := l.next; @@ -2116,7 +2098,7 @@ MODULE DuniterBlockchain; END; END; - sentriesS := U.NewSet(); + sentriesS := U.NewSet(); sentriesI.Attach(sentriesS); n := IdLenM(); IF n = 0 THEN RETURN END; n := SHORT(ENTIER(Math.Ceiling(Math.Power(n, 1 / pars.stepMax)))); @@ -2177,7 +2159,7 @@ MODULE DuniterBlockchain; END; Strings.StringToLInt(cur.fields[1], secureNow, res); ASSERT(res = 0, 105); END; - RemoveExpiredIds(now, secureNow); + RevokeExpiredIds(now, secureNow); RemoveExpiredCerts(now, secureNow); (* Élimine toutes les certifications expirées avec réversibilité dans secureGap *) END; database.WritePlace(undoListPlace, undoList); @@ -2290,12 +2272,6 @@ MODULE DuniterBlockchain; BA.Collect; END UpdateAll; - PROCEDURE FixIsFree* (if: IsFree); - - BEGIN (*FixIsFree*) - isFree := if; - END FixIsFree; - PROCEDURE Init; VAR @@ -2311,7 +2287,6 @@ MODULE DuniterBlockchain; ss: BA.TimeString; BEGIN (*Init*) - isFree := NIL; duniBase := ''; l := Files.dir.This(initDir); L.log.Err(l.res, initDir); v := Views.OldView(l, initName); diff --git a/Server version/Sources/Duniter/Sandbox.txt b/Server version/Sources/Duniter/Sandbox.txt index 2e994bc..8aa0fa1 100644 --- a/Server version/Sources/Duniter/Sandbox.txt +++ b/Server version/Sources/Duniter/Sandbox.txt @@ -544,13 +544,13 @@ MODULE DuniterSandbox; VAR t, tt: S.Table; - i, n, bnb: INTEGER; + i, n: INTEGER; cur: CurId; id: Identity; hE: IdHashE; e: A.Elem; b: BOOLEAN; - now, exp: LONGINT; + now: LONGINT; hash: Hash; r: S.Row; pub: Pubkey; @@ -730,21 +730,10 @@ MODULE DuniterSandbox; L.log.Msg("End loading sandbox. Time spent: " + s); END Scan; - PROCEDURE IsFree (IN p: Pubkey): BOOLEAN; - - VAR - - pos: CertPos; - - BEGIN (*IsFree*) - RETURN ~CertFrom(p, pos); - END IsFree; - PROCEDURE Init; BEGIN (*Init*) B.AddUpdateProc(Scan); - B.FixIsFree(IsFree); END Init; BEGIN (*DuniterSandbox*) diff --git a/Server version/Sources/Duniter/Server.txt b/Server version/Sources/Duniter/Server.txt index 60acf28..65fa7fd 100644 --- a/Server version/Sources/Duniter/Server.txt +++ b/Server version/Sources/Duniter/Server.txt @@ -22,7 +22,7 @@ MODULE DuniterServer; CONST - version = "2.3.0se"; + version = "2.3.2se"; rsrcDir = "Duniter/Rsrc"; (* Directory for the two following files *) parametersName = "Parameters.txt"; (* File containing the greatest allowed allocated memory size and the longest run time for W.CalcPermutations *) @@ -37,7 +37,7 @@ MODULE DuniterServer; maxSize: LONGINT; (* Greatest allowed allocated memory size *) (* Write the metadata duration, f, cNb & dNb with the help of fo, in json format; duration is the computation duration, f is the DuniterWotWizard.File structure, cNb and dNb are respectively the numbers of internal certifications and of external dossiers *) - PROCEDURE WriteMeta (IN fo: TextMappers.Formatter; duration: LONGINT; f: W.File; cNb, dNb: INTEGER); + PROCEDURE WriteMeta (IN fo: TextMappers.Formatter; duration: LONGINT; f: W.File; permutations, cNb, dNb: INTEGER); VAR @@ -140,6 +140,8 @@ MODULE DuniterServer; BA.TimestampToString(B.Now(), s); J.PushString(s); J.BuildField("now"); + J.PushInteger(permutations); + J.BuildField("permutations"); BA.TimeToString(duration, ss); J.PushString(ss); J.BuildField("computation_duration"); @@ -214,7 +216,7 @@ MODULE DuniterServer; occur: A.Tree; loc: Files.Locator; name: Files.Name; - res, cNb, dNb: INTEGER; + res, cNb, dNb, permutations: INTEGER; t: TextModels.Model; fo: TextMappers.Formatter; nowS: BA.DateTime; @@ -223,7 +225,7 @@ MODULE DuniterServer; BEGIN (*StoreText*) ti := Services.Ticks(); - IF ~W.BuildEntries(f, cNb, dNb, occur) THEN + IF ~W.BuildEntries(f, permutations, cNb, dNb, occur) THEN A.New(occur); END; duration := Services.Ticks() - ti; @@ -232,7 +234,7 @@ MODULE DuniterServer; loc := Files.dir.This(""); L.log.Err(loc.res, ""); t := TextModels.dir.New(); fo.ConnectTo(t); - WriteMeta(fo, duration, f, cNb, dNb); + WriteMeta(fo, duration, f, permutations, cNb, dNb); name := textMeta; Views.Register(TextViews.dir.New(t), Views.dontAsk, loc, name, BA.utf8Conv, res); L.log.Err(res, name); diff --git a/Server version/Sources/Duniter/WotWizard.txt b/Server version/Sources/Duniter/WotWizard.txt index a5d552e..e8b831a 100644 --- a/Server version/Sources/Duniter/WotWizard.txt +++ b/Server version/Sources/Duniter/WotWizard.txt @@ -34,8 +34,6 @@ MODULE DuniterWotWizard; LIS = SIZE(LONGINT); RES = SIZE(REAL); PTRS = SIZE(ANYPTR); - - unknownId = "***"; TYPE @@ -125,8 +123,6 @@ MODULE DuniterWotWizard; VAR - unknown: B.String; - maxSize-: LONGINT; (* Maximum allowed memory size for the execution of CalcPermutations *) (* log: TextMappers.Formatter; @@ -822,7 +818,7 @@ MODULE DuniterWotWizard; END CalcPermutations; (* Merge the Set(s) returned by CalcPermutations and combine their probabilities; return the list of entries sorted by date(s) in occurDate) *) - PROCEDURE CalcEntries* (f: File; OUT occurDate: A.Tree): BOOLEAN; + PROCEDURE CalcEntries* (f: File; OUT permutations: INTEGER; OUT occurDate: A.Tree): BOOLEAN; VAR @@ -839,6 +835,8 @@ MODULE DuniterWotWizard; debug := NIL; IF CalcPermutations(f, debug, sets) THEN + permutations := sets.NumberOfElems(); + (* Computing of Propagation(s) with their proba(s) *) A.New(occur); e := sets.Next(NIL); @@ -913,15 +911,15 @@ MODULE DuniterWotWizard; VAR - ok, okP, b: BOOLEAN; + ok, okP, b, bb: BOOLEAN; pos, posI: S.CertPos; from, to: B.Pubkey; - toHash: S.Hash; - i, j, nbCertifs, princCertif: INTEGER; + toHash, h: S.Hash; + i, j, nbCertifs, princCertif, bnb: INTEGER; exp, date, mt, t: LONGINT; d: Dossier; c: Certif; - uid: B.String; + uid, uid1: B.String; certs, cert: PubList; s: ARRAY 11 OF CHAR; cdL, l: CdList; @@ -932,68 +930,74 @@ MODULE DuniterWotWizard; dNb := 0; ok := S.IdNextHash(TRUE, toHash); WHILE ok DO - nbCertifs := 0; certs := NIL; - IF S.CertTo(toHash, pos) THEN - posI := pos; - REPEAT - okP := pos.CertNextPos(from, toHash); - IF okP THEN - b := S.Cert(from, toHash, to, exp) ; ASSERT(b, 100); - FixCertNextDate(from, date); - IF date <= exp THEN (* Not-expired certification *) - INC(nbCertifs); - NEW(cert); NEW(cert.pub); cert.pub^ := from; cert.date := date; - cert.next := certs; certs := cert; + b := S.IdHash(toHash, to, uid, exp); ASSERT(b); + b := B.IdPub(to, uid1); bb := B.IdUid(uid, to); + IF ~b & ~bb OR b & (uid$ = uid1$) & B.IdPubComplete(to, uid, b, h, bnb, exp) & (exp = BA.missing) THEN + nbCertifs := 0; certs := NIL; + IF S.CertTo(toHash, pos) THEN + posI := pos; + REPEAT + okP := pos.CertNextPos(from, toHash); + IF okP THEN + b := S.Cert(from, toHash, to, exp) ; ASSERT(b, 100); + FixCertNextDate(from, date); + IF date <= exp THEN (* Not-expired certification *) + INC(nbCertifs); + NEW(cert); NEW(cert.pub); cert.pub^ := from; cert.date := date; + cert.next := certs; certs := cert; + END; END; - END; - UNTIL ~okP; - END; - IF (nbCertifs >= B.pars.sigQty) & NotTooFar(certs, nbCertifs, princCertif, proportionOfSentries) THEN - INC(dNb); - NEW(d); NEW(d.pub); - NEW(l.next); l := l.next; - l.cd := d; - d.princCertif := princCertif; - d.proportionOfSentries := proportionOfSentries; - b := S.IdHash(toHash, d.pub, d.id, d.limit); ASSERT(b, 101); - NEW(d.certifs, nbCertifs); - j := 0; - pos := posI; - okP := pos.CertNextPos(from, toHash); ASSERT(okP, 102); - REPEAT - b := S.Cert(from, toHash, to, exp); ASSERT(b, 103); - NEW(c); NEW(c.fromP); - c.fromP^ := from; - b := B.IdPub(from, c.from); ASSERT(b, 104); - FixCertNextDate(from, c.date); - c.limit := exp; - IF c.date <= c.limit THEN - d.certifs[j] := c; - INC(j); - END; - okP := pos.CertNextPos(from, toHash); - UNTIL ~okP; + UNTIL ~okP; + END; + IF (nbCertifs >= B.pars.sigQty) & NotTooFar(certs, nbCertifs, princCertif, proportionOfSentries) THEN + INC(dNb); + NEW(d); NEW(d.pub); + NEW(l.next); l := l.next; + l.cd := d; + d.princCertif := princCertif; + d.proportionOfSentries := proportionOfSentries; + b := S.IdHash(toHash, d.pub, d.id, d.limit); ASSERT(b, 101); + NEW(d.certifs, nbCertifs); + j := 0; + pos := posI; + okP := pos.CertNextPos(from, toHash); ASSERT(okP, 102); + REPEAT + b := S.Cert(from, toHash, to, exp); ASSERT(b, 103); + NEW(c); NEW(c.fromP); + c.fromP^ := from; + b := B.IdPub(from, c.from); ASSERT(b, 104); + FixCertNextDate(from, c.date); + c.limit := exp; + IF c.date <= c.limit THEN + d.certifs[j] := c; + INC(j); + END; + okP := pos.CertNextPos(from, toHash); + UNTIL ~okP; + END; + ok := S.IdNextHash(FALSE, toHash); END; - ok := S.IdNextHash(FALSE, toHash); END; cNb := 0; ok := S.CertNextTo(TRUE, pos); WHILE ok DO - IF pos.CertNextPos(from, toHash) & S.Cert(from, toHash, to, exp) & B.IdPub(to, uid) THEN + IF pos.CertNextPos(from, toHash) & S.Cert(from, toHash, to, exp) THEN REPEAT - NEW(c); NEW(c.fromP); - c.fromP^ := from; - b := B.IdPub(from, c.from); ASSERT(b, 105); - c.to := uid; - FixCertNextDate(from, c.date); - c.limit := exp; - (* Si la certif n'est pas encore passée au dernier bloc alors qu'elle aurait dû passer à ce bloc ou avant, il y a peu de chance qu'elle passe plus tard et il vaut mieux l'enlever ; il faut aussi l'enlever si elle a dépassé sa date limite ; peut-être inutile maintenant *) - mt := 0; - b := B.TimeOf(B.LastBlock() - 1, mt, t); ASSERT(b OR (B.LastBlock() = 0), 106); - IF (c.date <= c.limit) & (c.date > mt) THEN - INC(cNb); - NEW(l.next); l := l.next; - l.cd := c; + IF B.IdPubComplete(to, uid, b, h, bnb, t) & b THEN + NEW(c); NEW(c.fromP); + c.fromP^ := from; + b := B.IdPub(from, c.from); ASSERT(b, 105); + c.to := uid; + FixCertNextDate(from, c.date); + c.limit := exp; + (* Si la certif n'est pas encore passée au dernier bloc alors qu'elle aurait dû passer à ce bloc ou avant, il y a peu de chance qu'elle passe plus tard et il vaut mieux l'enlever ; il faut aussi l'enlever si elle a dépassé sa date limite ; peut-être inutile maintenant *) + mt := 0; + b := B.TimeOf(B.LastBlock() - 1, mt, t); ASSERT(b OR (B.LastBlock() = 0), 106); + IF (c.date <= c.limit) & (c.date > mt) THEN + INC(cNb); + NEW(l.next); l := l.next; + l.cd := c; + END; END; UNTIL ~(pos.CertNextPos(from, toHash) & S.Cert(from, toHash, to, exp)); END; @@ -1019,7 +1023,7 @@ MODULE DuniterWotWizard; END FillFile; (* Calculate the current set of entries, sorted by dates (occur) and by names (invOccur) *) - PROCEDURE BuildEntries* (OUT f: File; OUT cNb, dNb: INTEGER; OUT occurDate: A.Tree): BOOLEAN; + PROCEDURE BuildEntries* (OUT f: File; OUT permutations, cNb, dNb: INTEGER; OUT occurDate: A.Tree): BOOLEAN; VAR @@ -1037,7 +1041,7 @@ MODULE DuniterWotWizard; L.log.Msg("Calculating entries"); t := Services.Ticks(); n := 0; - b := CalcEntries(CopyFile(f, 0, n), occurDate); + b := CalcEntries(CopyFile(f, 0, n), permutations, occurDate); BA.TimeToString(Services.Ticks() - t, ts); L.log.Msg("End calculating entries. Time spent: " + ts); RETURN b; @@ -1050,7 +1054,6 @@ MODULE DuniterWotWizard; END ChangeParameters; BEGIN (*DuniterWotWizard*) - NEW(unknown, LEN(unknownId) + 1); unknown^ := unknownId; maxSize := maxSizeDef; (** log.ConnectTo(StdLog.text); diff --git a/Server version/Sources/Util/Sets.txt b/Server version/Sources/Util/Sets.txt index 67a7929..230b71a 100644 --- a/Server version/Sources/Util/Sets.txt +++ b/Server version/Sources/Util/Sets.txt @@ -34,12 +34,17 @@ MODULE UtilSets; END; Set* = POINTER TO LIMITED RECORD (* Set of non-negative integers. *) - nbElems-, (* Number of elements in the set. *) - pos, posE: INTEGER; - elems, cour: Segment; + nbElems-: INTEGER; (* Number of elements in the set. *) + elems: Segment; END; TableVer = ARRAY 2, 2 OF BYTE; + + SetIterator* = RECORD + s: Set; + cour: Segment; + pos, posE: INTEGER; + END; PROCEDURE InsereSegment (apresSeg: Segment; plein, vide: INTEGER); @@ -65,7 +70,6 @@ MODULE UtilSets; s.elems.largeurs[0] := taSet; s.elems.suivant := s.elems; s.elems.precedent := s.elems; - s.cour := NIL; END Empty; (* Creates and returns a new empty set. *) @@ -117,7 +121,6 @@ MODULE UtilSets; BEGIN (*Trans*) s.nbElems := src.nbElems; s.elems := src.elems; - s.cour := NIL; END Trans; (* Creates and returns a copy of s.*) @@ -539,89 +542,84 @@ MODULE UtilSets; RETURN se # t; END NextElem; + PROCEDURE (VAR i: SetIterator) Attach* (s: Set), NEW; + + BEGIN (*Attach*) + ASSERT(s # NIL, 20); + i.s := s; + i.cour := NIL; + END Attach; + (* On return, min and max contain the first interval of the set s. Returns TRUE if such an interval exists. Usage: ok:= s.First(a, b); WHILE ok DO ... ok:= s.Next(a, b) END; *) - PROCEDURE (s: Set) First* (OUT min, max: INTEGER): BOOLEAN, NEW; + PROCEDURE (VAR i: SetIterator) First* (OUT min, max: INTEGER): BOOLEAN, NEW; BEGIN (*First*) - IF s.IsEmpty() THEN + ASSERT(i.s # NIL, 20); + IF i.s.IsEmpty() THEN RETURN FALSE; END; - s.cour := s.elems.suivant; - s.pos := sMin + s.elems.largeurs[0]; - min := s.pos; - max := min + s.cour.largeurs[1] - 1; + i.cour := i.s.elems.suivant; + i.pos := sMin + i.s.elems.largeurs[0]; + min := i.pos; + max := min + i.cour.largeurs[1] - 1; RETURN TRUE; END First; (* On return, min and max contain the next interval of the set s. Returns TRUE if such an interval exists. s.First must have been called once before s.Next. Usage: ok:= s.First(a, b); WHILE ok DO ... ok:= s.Next(a, b) END; *) - PROCEDURE (s: Set) Next* (OUT min, max: INTEGER): BOOLEAN, NEW; + PROCEDURE (VAR i: SetIterator) Next* (OUT min, max: INTEGER): BOOLEAN, NEW; BEGIN (*Next*) - ASSERT(s.cour # NIL, 20); - s.pos := s.pos + s.cour.largeurs[1] + s.cour.largeurs[0]; - s.cour := s.cour.suivant; - IF s.cour = s.elems THEN - s.cour := NIL; + ASSERT(i.s # NIL, 20); + ASSERT(i.cour # NIL, 21); + i.pos := i.pos + i.cour.largeurs[1] + i.cour.largeurs[0]; + i.cour := i.cour.suivant; + IF i.cour = i.s.elems THEN + i.cour := NIL; RETURN FALSE; END; - min := s.pos; - max := min + s.cour.largeurs[1] - 1; + min := i.pos; + max := min + i.cour.largeurs[1] - 1; RETURN TRUE; END Next; - PROCEDURE (s: Set) FirstE* (OUT e: INTEGER): BOOLEAN, NEW; + PROCEDURE (VAR i: SetIterator) FirstE* (OUT e: INTEGER): BOOLEAN, NEW; BEGIN (*FirstE*) - IF s.IsEmpty() THEN + ASSERT(i.s # NIL, 20); + IF i.s.IsEmpty() THEN RETURN FALSE; END; - s.cour := s.elems.suivant; - s.pos := sMin + s.elems.largeurs[0]; - s.posE := s.pos; - e := s.pos; + i.cour := i.s.elems.suivant; + i.pos := sMin + i.s.elems.largeurs[0]; + i.posE := i.pos; + e := i.posE; RETURN TRUE; END FirstE; - PROCEDURE (s: Set) NextE* (OUT e: INTEGER): BOOLEAN, NEW; + PROCEDURE (VAR i: SetIterator) NextE* (OUT e: INTEGER): BOOLEAN, NEW; VAR max: INTEGER; BEGIN (*NextE*) - ASSERT(s.cour # NIL, 20); - max := s.pos + s.cour.largeurs[1] - 1; - IF s.posE < max THEN - INC(s.posE); - e := s.posE; + ASSERT(i.s # NIL, 20); + ASSERT(i.cour # NIL, 21); + max := i.pos + i.cour.largeurs[1] - 1; + IF i.posE < max THEN + INC(i.posE); + e := i.posE; RETURN TRUE; END; - s.pos := s.pos + s.cour.largeurs[1] + s.cour.largeurs[0]; - s.cour := s.cour.suivant; - IF s.cour = s.elems THEN - s.cour := NIL; + i.pos := i.pos + i.cour.largeurs[1] + i.cour.largeurs[0]; + i.cour := i.cour.suivant; + IF i.cour = i.s.elems THEN + i.cour := NIL; RETURN FALSE; END; - s.posE := s.pos; - e := s.posE; + i.posE := i.pos; + e := i.posE; RETURN TRUE; END NextE; - PROCEDURE (s: Set) NbOfElems* (): INTEGER, NEW; - - VAR - - n, min, max: INTEGER; - ok: BOOLEAN; - - BEGIN (*NbOfElems*) - n := 0; - ok := s.First(min, max); - WHILE ok DO - INC(n, max - min + 1); - ok := s.Next(min, max); - END; - RETURN n; - END NbOfElems; - END UtilSets.