|
@@ -62,7 +62,7 @@ Type
|
|
Class Function GetRewardForNewLine(line_index: Cardinal): UInt64;
|
|
Class Function GetRewardForNewLine(line_index: Cardinal): UInt64;
|
|
Class Function TargetToCompact(target: TRawBytes): Cardinal;
|
|
Class Function TargetToCompact(target: TRawBytes): Cardinal;
|
|
Class Function TargetFromCompact(encoded: Cardinal): TRawBytes;
|
|
Class Function TargetFromCompact(encoded: Cardinal): TRawBytes;
|
|
- Class Function GetNewTarget(vteorical, vreal: Cardinal; Const actualTarget: TRawBytes): TRawBytes;
|
|
|
|
|
|
+ Class Function GetNewTarget(vteorical, vreal: Cardinal; protocol_version : Integer; isSlowMovement : Boolean; Const actualTarget: TRawBytes): TRawBytes;
|
|
Class Procedure CalcProofOfWork_Part1(const operationBlock : TOperationBlock; out Part1 : TRawBytes);
|
|
Class Procedure CalcProofOfWork_Part1(const operationBlock : TOperationBlock; out Part1 : TRawBytes);
|
|
Class Procedure CalcProofOfWork_Part3(const operationBlock : TOperationBlock; out Part3 : TRawBytes);
|
|
Class Procedure CalcProofOfWork_Part3(const operationBlock : TOperationBlock; out Part3 : TRawBytes);
|
|
Class Procedure CalcProofOfWork(const operationBlock : TOperationBlock; out PoW : TRawBytes);
|
|
Class Procedure CalcProofOfWork(const operationBlock : TOperationBlock; out PoW : TRawBytes);
|
|
@@ -193,12 +193,17 @@ Type
|
|
TAccountKeyArray = array of TAccountKey;
|
|
TAccountKeyArray = array of TAccountKey;
|
|
|
|
|
|
// This is a class to quickly find accountkeys and their respective account number/s
|
|
// This is a class to quickly find accountkeys and their respective account number/s
|
|
|
|
+
|
|
|
|
+ { TOrderedAccountKeysList }
|
|
|
|
+
|
|
TOrderedAccountKeysList = Class
|
|
TOrderedAccountKeysList = Class
|
|
Private
|
|
Private
|
|
FAutoAddAll : Boolean;
|
|
FAutoAddAll : Boolean;
|
|
FAccountList : TPCSafeBox;
|
|
FAccountList : TPCSafeBox;
|
|
- FOrderedAccountKeysList : TList; // An ordered list of pointers to quickly find account keys in account list
|
|
|
|
- Function Find(Const AccountKey: TAccountKey; var Index: Integer): Boolean;
|
|
|
|
|
|
+ FOrderedAccountKeysList : TPCThreadList; // An ordered list of pointers to quickly find account keys in account list
|
|
|
|
+ FTotalChanges : Integer;
|
|
|
|
+ Function Find(lockedList : TList; Const AccountKey: TAccountKey; var Index: Integer): Boolean;
|
|
|
|
+ function GetAccountKeyChanges(index : Integer): Integer;
|
|
function GetAccountKeyList(index: Integer): TOrderedCardinalList;
|
|
function GetAccountKeyList(index: Integer): TOrderedCardinalList;
|
|
function GetAccountKey(index: Integer): TAccountKey;
|
|
function GetAccountKey(index: Integer): TAccountKey;
|
|
protected
|
|
protected
|
|
@@ -213,10 +218,15 @@ Type
|
|
Function IndexOfAccountKey(Const AccountKey : TAccountKey) : Integer;
|
|
Function IndexOfAccountKey(Const AccountKey : TAccountKey) : Integer;
|
|
Property AccountKeyList[index : Integer] : TOrderedCardinalList read GetAccountKeyList;
|
|
Property AccountKeyList[index : Integer] : TOrderedCardinalList read GetAccountKeyList;
|
|
Property AccountKey[index : Integer] : TAccountKey read GetAccountKey;
|
|
Property AccountKey[index : Integer] : TAccountKey read GetAccountKey;
|
|
|
|
+ Property AccountKeyChanges[index : Integer] : Integer read GetAccountKeyChanges;
|
|
|
|
+ procedure ClearAccountKeyChanges;
|
|
Function Count : Integer;
|
|
Function Count : Integer;
|
|
Property SafeBox : TPCSafeBox read FAccountList;
|
|
Property SafeBox : TPCSafeBox read FAccountList;
|
|
Procedure Clear;
|
|
Procedure Clear;
|
|
function ToArray : TAccountKeyArray;
|
|
function ToArray : TAccountKeyArray;
|
|
|
|
+ function Lock : TList;
|
|
|
|
+ procedure Unlock;
|
|
|
|
+ function HasAccountKeyChanged : Boolean;
|
|
End;
|
|
End;
|
|
|
|
|
|
// Maintans a Cardinal ordered (without duplicates) list with TRawData each
|
|
// Maintans a Cardinal ordered (without duplicates) list with TRawData each
|
|
@@ -578,10 +588,10 @@ end;
|
|
|
|
|
|
{ TPascalCoinProtocol }
|
|
{ TPascalCoinProtocol }
|
|
|
|
|
|
-class function TPascalCoinProtocol.GetNewTarget(vteorical, vreal: Cardinal; const actualTarget: TRawBytes): TRawBytes;
|
|
|
|
|
|
+class function TPascalCoinProtocol.GetNewTarget(vteorical, vreal: Cardinal; protocol_version : Integer; isSlowMovement : Boolean; const actualTarget: TRawBytes): TRawBytes;
|
|
Var
|
|
Var
|
|
bnact, bnaux: TBigNum;
|
|
bnact, bnaux: TBigNum;
|
|
- tsTeorical, tsReal, factor1000, factor1000Min, factor1000Max: Int64;
|
|
|
|
|
|
+ tsTeorical, tsReal, factor, factorMin, factorMax, factorDivider: Int64;
|
|
begin
|
|
begin
|
|
{ Given a teorical time in seconds (vteorical>0) and a real time in seconds (vreal>0)
|
|
{ Given a teorical time in seconds (vteorical>0) and a real time in seconds (vreal>0)
|
|
and an actual target, calculates a new target
|
|
and an actual target, calculates a new target
|
|
@@ -594,22 +604,48 @@ begin
|
|
}
|
|
}
|
|
tsTeorical := vteorical;
|
|
tsTeorical := vteorical;
|
|
tsReal := vreal;
|
|
tsReal := vreal;
|
|
- factor1000 := (((tsTeorical - tsReal) * 1000) DIV (tsTeorical)) * (-1);
|
|
|
|
-
|
|
|
|
- { Important: Note that a -500 is the same that divide by 2 (-100%), and
|
|
|
|
- 1000 is the same that multiply by 2 (+100%), so we limit increase
|
|
|
|
- in a limit [-500..+1000] for a complete (CT_CalcNewTargetBlocksAverage DIV 2) round }
|
|
|
|
- if CT_CalcNewTargetBlocksAverage>1 then begin
|
|
|
|
- factor1000Min := (-500) DIV (CT_CalcNewTargetBlocksAverage DIV 2);
|
|
|
|
- factor1000Max := (1000) DIV (CT_CalcNewTargetBlocksAverage DIV 2);
|
|
|
|
|
|
+
|
|
|
|
+ { On protocol 1,2 the increment was limited in a integer value between -10..20
|
|
|
|
+ On protocol 3 we increase decimals, so increment could be a integer
|
|
|
|
+ between -1000..2000, using 2 more decimals for percent. Also will introduce
|
|
|
|
+ a "isSlowMovement" variable that will limit to a maximum +-0.5% increment}
|
|
|
|
+ if (protocol_version<CT_PROTOCOL_3) then begin
|
|
|
|
+ factorDivider := 1000;
|
|
|
|
+ factor := (((tsTeorical - tsReal) * 1000) DIV (tsTeorical)) * (-1);
|
|
|
|
+
|
|
|
|
+ { Important: Note that a -500 is the same that divide by 2 (-100%), and
|
|
|
|
+ 1000 is the same that multiply by 2 (+100%), so we limit increase
|
|
|
|
+ in a limit [-500..+1000] for a complete (CT_CalcNewTargetBlocksAverage DIV 2) round }
|
|
|
|
+ if CT_CalcNewTargetBlocksAverage>1 then begin
|
|
|
|
+ factorMin := (-500) DIV (CT_CalcNewTargetBlocksAverage DIV 2);
|
|
|
|
+ factorMax := (1000) DIV (CT_CalcNewTargetBlocksAverage DIV 2);
|
|
|
|
+ end else begin
|
|
|
|
+ factorMin := (-500);
|
|
|
|
+ factorMax := (1000);
|
|
|
|
+ end;
|
|
end else begin
|
|
end else begin
|
|
- factor1000Min := (-500);
|
|
|
|
- factor1000Max := (1000);
|
|
|
|
|
|
+ // Protocol 3:
|
|
|
|
+ factorDivider := 100000;
|
|
|
|
+ If (isSlowMovement) then begin
|
|
|
|
+ // Limit to 0.5% instead of 2% (When CT_CalcNewTargetBlocksAverage = 100)
|
|
|
|
+ factorMin := (-50000) DIV (CT_CalcNewTargetBlocksAverage * 2);
|
|
|
|
+ factorMax := (100000) DIV (CT_CalcNewTargetBlocksAverage * 2);
|
|
|
|
+ end else begin
|
|
|
|
+ if CT_CalcNewTargetBlocksAverage>1 then begin
|
|
|
|
+ factorMin := (-50000) DIV (CT_CalcNewTargetBlocksAverage DIV 2);
|
|
|
|
+ factorMax := (100000) DIV (CT_CalcNewTargetBlocksAverage DIV 2);
|
|
|
|
+ end else begin
|
|
|
|
+ factorMin := (-50000);
|
|
|
|
+ factorMax := (100000);
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
- if factor1000 < factor1000Min then factor1000 := factor1000Min
|
|
|
|
- else if factor1000 > factor1000Max then factor1000 := factor1000Max
|
|
|
|
- else if factor1000=0 then begin
|
|
|
|
|
|
+ factor := (((tsTeorical - tsReal) * factorDivider) DIV (tsTeorical)) * (-1);
|
|
|
|
+
|
|
|
|
+ if factor < factorMin then factor := factorMin
|
|
|
|
+ else if factor > factorMax then factor := factorMax
|
|
|
|
+ else if factor=0 then begin
|
|
Result := actualTarget;
|
|
Result := actualTarget;
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
@@ -620,7 +656,7 @@ begin
|
|
bnact.RawValue := actualTarget;
|
|
bnact.RawValue := actualTarget;
|
|
bnaux := bnact.Copy;
|
|
bnaux := bnact.Copy;
|
|
try
|
|
try
|
|
- bnact.Multiply(factor1000).Divide(1000).Add(bnaux);
|
|
|
|
|
|
+ bnact.Multiply(factor).Divide(factorDivider).Add(bnaux);
|
|
finally
|
|
finally
|
|
bnaux.Free;
|
|
bnaux.Free;
|
|
end;
|
|
end;
|
|
@@ -3266,7 +3302,7 @@ begin
|
|
tsTeorical := (CalcBack * CT_NewLineSecondsAvg);
|
|
tsTeorical := (CalcBack * CT_NewLineSecondsAvg);
|
|
tsReal := (ts1 - ts2);
|
|
tsReal := (ts1 - ts2);
|
|
If (protocolVersion=CT_PROTOCOL_1) then begin
|
|
If (protocolVersion=CT_PROTOCOL_1) then begin
|
|
- Result := TPascalCoinProtocol.GetNewTarget(tsTeorical, tsReal,TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target));
|
|
|
|
|
|
+ Result := TPascalCoinProtocol.GetNewTarget(tsTeorical, tsReal,protocolVersion,False,TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target));
|
|
end else if (protocolVersion<=CT_PROTOCOL_3) then begin
|
|
end else if (protocolVersion<=CT_PROTOCOL_3) then begin
|
|
CalcBack := CalcBack DIV CT_CalcNewTargetLimitChange_SPLIT;
|
|
CalcBack := CalcBack DIV CT_CalcNewTargetLimitChange_SPLIT;
|
|
If CalcBack=0 then CalcBack := 1;
|
|
If CalcBack=0 then CalcBack := 1;
|
|
@@ -3280,15 +3316,15 @@ begin
|
|
If ((tsTeorical>tsReal) and (tsTeoricalStop>tsRealStop))
|
|
If ((tsTeorical>tsReal) and (tsTeoricalStop>tsRealStop))
|
|
Or
|
|
Or
|
|
((tsTeorical<tsReal) and (tsTeoricalStop<tsRealStop)) then begin
|
|
((tsTeorical<tsReal) and (tsTeoricalStop<tsRealStop)) then begin
|
|
- Result := TPascalCoinProtocol.GetNewTarget(tsTeorical, tsReal,TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target));
|
|
|
|
|
|
+ Result := TPascalCoinProtocol.GetNewTarget(tsTeorical, tsReal,protocolVersion,False,TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target));
|
|
end else begin
|
|
end else begin
|
|
if (protocolVersion=CT_PROTOCOL_2) then begin
|
|
if (protocolVersion=CT_PROTOCOL_2) then begin
|
|
// Nothing to do!
|
|
// Nothing to do!
|
|
Result:=TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target);
|
|
Result:=TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target);
|
|
end else begin
|
|
end else begin
|
|
// New on V3 protocol:
|
|
// New on V3 protocol:
|
|
- // Harmonization of the sinusoidal effect modifying the rise / fall by 50% calculating over the "stop" area
|
|
|
|
- Result := TPascalCoinProtocol.GetNewTarget(tsTeoricalStop, (tsTeoricalStop + tsRealStop) DIV 2,TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target));
|
|
|
|
|
|
+ // Harmonization of the sinusoidal effect modifying the rise / fall over the "stop" area
|
|
|
|
+ Result := TPascalCoinProtocol.GetNewTarget(tsTeoricalStop,tsRealStop,protocolVersion,True,TPascalCoinProtocol.TargetFromCompact(lastBlock.compact_target));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end else begin
|
|
end else begin
|
|
@@ -4313,8 +4349,11 @@ Type
|
|
TOrderedAccountKeyList = Record
|
|
TOrderedAccountKeyList = Record
|
|
rawaccountkey : TRawBytes;
|
|
rawaccountkey : TRawBytes;
|
|
accounts_number : TOrderedCardinalList;
|
|
accounts_number : TOrderedCardinalList;
|
|
|
|
+ changes_counter : Integer;
|
|
end;
|
|
end;
|
|
POrderedAccountKeyList = ^TOrderedAccountKeyList;
|
|
POrderedAccountKeyList = ^TOrderedAccountKeyList;
|
|
|
|
+Const
|
|
|
|
+ CT_TOrderedAccountKeyList_NUL : TOrderedAccountKeyList = (rawaccountkey:'';accounts_number:Nil;changes_counter:0);
|
|
|
|
|
|
function SortOrdered(Item1, Item2: Pointer): Integer;
|
|
function SortOrdered(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
begin
|
|
@@ -4324,78 +4363,136 @@ end;
|
|
procedure TOrderedAccountKeysList.AddAccountKey(const AccountKey: TAccountKey);
|
|
procedure TOrderedAccountKeysList.AddAccountKey(const AccountKey: TAccountKey);
|
|
Var P : POrderedAccountKeyList;
|
|
Var P : POrderedAccountKeyList;
|
|
i,j : Integer;
|
|
i,j : Integer;
|
|
|
|
+ lockedList : TList;
|
|
begin
|
|
begin
|
|
- if Not Find(AccountKey,i) then begin
|
|
|
|
- New(P);
|
|
|
|
- P^.rawaccountkey := TAccountComp.AccountKey2RawString(AccountKey);
|
|
|
|
- P^.accounts_number := TOrderedCardinalList.Create;
|
|
|
|
- FOrderedAccountKeysList.Insert(i,P);
|
|
|
|
- // Search this key in the AccountsList and add all...
|
|
|
|
- j := 0;
|
|
|
|
- if Assigned(FAccountList) then begin
|
|
|
|
- For i:=0 to FAccountList.AccountsCount-1 do begin
|
|
|
|
- If TAccountComp.EqualAccountKeys(FAccountList.Account(i).accountInfo.accountkey,AccountKey) then begin
|
|
|
|
- // Note: P^.accounts will be ascending ordered due to "for i:=0 to ..."
|
|
|
|
- P^.accounts_number.Add(i);
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ if Not Find(lockedList,AccountKey,i) then begin
|
|
|
|
+ New(P);
|
|
|
|
+ P^ := CT_TOrderedAccountKeyList_NUL;
|
|
|
|
+ P^.rawaccountkey := TAccountComp.AccountKey2RawString(AccountKey);
|
|
|
|
+ P^.accounts_number := TOrderedCardinalList.Create;
|
|
|
|
+ inc(P^.changes_counter);
|
|
|
|
+ inc(FTotalChanges);
|
|
|
|
+ lockedList.Insert(i,P);
|
|
|
|
+ // Search this key in the AccountsList and add all...
|
|
|
|
+ j := 0;
|
|
|
|
+ if Assigned(FAccountList) then begin
|
|
|
|
+ For i:=0 to FAccountList.AccountsCount-1 do begin
|
|
|
|
+ If TAccountComp.EqualAccountKeys(FAccountList.Account(i).accountInfo.accountkey,AccountKey) then begin
|
|
|
|
+ // Note: P^.accounts will be ascending ordered due to "for i:=0 to ..."
|
|
|
|
+ P^.accounts_number.Add(i);
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
+ TLog.NewLog(ltdebug,Classname,Format('Adding account key (%d of %d) %s',[j,FAccountList.AccountsCount,TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(AccountKey))]));
|
|
|
|
+ end else begin
|
|
|
|
+ TLog.NewLog(ltdebug,Classname,Format('Adding account key (no Account List) %s',[TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(AccountKey))]));
|
|
end;
|
|
end;
|
|
- TLog.NewLog(ltdebug,Classname,Format('Adding account key (%d of %d) %s',[j,FAccountList.AccountsCount,TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(AccountKey))]));
|
|
|
|
- end else begin
|
|
|
|
- TLog.NewLog(ltdebug,Classname,Format('Adding account key (no Account List) %s',[TCrypto.ToHexaString(TAccountComp.AccountKey2RawString(AccountKey))]));
|
|
|
|
end;
|
|
end;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TOrderedAccountKeysList.AddAccounts(const AccountKey: TAccountKey; const accounts: array of Cardinal);
|
|
procedure TOrderedAccountKeysList.AddAccounts(const AccountKey: TAccountKey; const accounts: array of Cardinal);
|
|
Var P : POrderedAccountKeyList;
|
|
Var P : POrderedAccountKeyList;
|
|
i,i2 : Integer;
|
|
i,i2 : Integer;
|
|
|
|
+ lockedList : TList;
|
|
begin
|
|
begin
|
|
- if Find(AccountKey,i) then begin
|
|
|
|
- P := POrderedAccountKeyList(FOrderedAccountKeysList[i]);
|
|
|
|
- end else if (FAutoAddAll) then begin
|
|
|
|
- New(P);
|
|
|
|
- P^.rawaccountkey := TAccountComp.AccountKey2RawString(AccountKey);
|
|
|
|
- P^.accounts_number := TOrderedCardinalList.Create;
|
|
|
|
- FOrderedAccountKeysList.Insert(i,P);
|
|
|
|
- end else exit;
|
|
|
|
- for i := Low(accounts) to High(accounts) do begin
|
|
|
|
- P^.accounts_number.Add(accounts[i]);
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ if Find(lockedList,AccountKey,i) then begin
|
|
|
|
+ P := POrderedAccountKeyList(lockedList[i]);
|
|
|
|
+ end else if (FAutoAddAll) then begin
|
|
|
|
+ New(P);
|
|
|
|
+ P^ := CT_TOrderedAccountKeyList_NUL;
|
|
|
|
+ P^.rawaccountkey := TAccountComp.AccountKey2RawString(AccountKey);
|
|
|
|
+ P^.accounts_number := TOrderedCardinalList.Create;
|
|
|
|
+ lockedList.Insert(i,P);
|
|
|
|
+ end else exit;
|
|
|
|
+ for i := Low(accounts) to High(accounts) do begin
|
|
|
|
+ P^.accounts_number.Add(accounts[i]);
|
|
|
|
+ end;
|
|
|
|
+ inc(P^.changes_counter);
|
|
|
|
+ inc(FTotalChanges);
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TOrderedAccountKeysList.Clear;
|
|
procedure TOrderedAccountKeysList.Clear;
|
|
begin
|
|
begin
|
|
- ClearAccounts(true);
|
|
|
|
|
|
+ Lock;
|
|
|
|
+ Try
|
|
|
|
+ ClearAccounts(true);
|
|
|
|
+ FTotalChanges := 1; // 1 = At least 1 change
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TOrderedAccountKeysList.ToArray : TAccountKeyArray;
|
|
function TOrderedAccountKeysList.ToArray : TAccountKeyArray;
|
|
var i : Integer;
|
|
var i : Integer;
|
|
begin
|
|
begin
|
|
- SetLength(Result, Count);
|
|
|
|
- for i := 0 to Count - 1 do Result[i] := Self.AccountKey[i];
|
|
|
|
|
|
+ Lock;
|
|
|
|
+ Try
|
|
|
|
+ SetLength(Result, Count);
|
|
|
|
+ for i := 0 to Count - 1 do Result[i] := Self.AccountKey[i];
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function TOrderedAccountKeysList.Lock: TList;
|
|
|
|
+begin
|
|
|
|
+ Result := FOrderedAccountKeysList.LockList;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TOrderedAccountKeysList.Unlock;
|
|
|
|
+begin
|
|
|
|
+ FOrderedAccountKeysList.UnlockList;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+function TOrderedAccountKeysList.HasAccountKeyChanged: Boolean;
|
|
|
|
+begin
|
|
|
|
+ Result := FTotalChanges>0;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TOrderedAccountKeysList.ClearAccounts(RemoveAccountList : Boolean);
|
|
procedure TOrderedAccountKeysList.ClearAccounts(RemoveAccountList : Boolean);
|
|
Var P : POrderedAccountKeyList;
|
|
Var P : POrderedAccountKeyList;
|
|
i : Integer;
|
|
i : Integer;
|
|
|
|
+ lockedList : TList;
|
|
begin
|
|
begin
|
|
- for i := 0 to FOrderedAccountKeysList.Count - 1 do begin
|
|
|
|
- P := FOrderedAccountKeysList[i];
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ for i := 0 to lockedList.Count - 1 do begin
|
|
|
|
+ P := lockedList[i];
|
|
|
|
+ inc(P^.changes_counter);
|
|
|
|
+ if RemoveAccountList then begin
|
|
|
|
+ P^.accounts_number.Free;
|
|
|
|
+ Dispose(P);
|
|
|
|
+ end else begin
|
|
|
|
+ P^.accounts_number.Clear;
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
if RemoveAccountList then begin
|
|
if RemoveAccountList then begin
|
|
- P^.accounts_number.Free;
|
|
|
|
- Dispose(P);
|
|
|
|
- end else begin
|
|
|
|
- P^.accounts_number.Clear;
|
|
|
|
|
|
+ lockedList.Clear;
|
|
end;
|
|
end;
|
|
- end;
|
|
|
|
- if RemoveAccountList then begin
|
|
|
|
- FOrderedAccountKeysList.Clear;
|
|
|
|
|
|
+ FTotalChanges:=lockedList.Count + 1; // At least 1 change
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TOrderedAccountKeysList.Count: Integer;
|
|
function TOrderedAccountKeysList.Count: Integer;
|
|
|
|
+var lockedList : TList;
|
|
begin
|
|
begin
|
|
- Result := FOrderedAccountKeysList.Count;
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ Result := lockedList.Count;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
constructor TOrderedAccountKeysList.Create(AccountList : TPCSafeBox; AutoAddAll : Boolean);
|
|
constructor TOrderedAccountKeysList.Create(AccountList : TPCSafeBox; AutoAddAll : Boolean);
|
|
@@ -4404,13 +4501,19 @@ begin
|
|
TLog.NewLog(ltdebug,Classname,'Creating an Ordered Account Keys List adding all:'+CT_TRUE_FALSE[AutoAddAll]);
|
|
TLog.NewLog(ltdebug,Classname,'Creating an Ordered Account Keys List adding all:'+CT_TRUE_FALSE[AutoAddAll]);
|
|
FAutoAddAll := AutoAddAll;
|
|
FAutoAddAll := AutoAddAll;
|
|
FAccountList := AccountList;
|
|
FAccountList := AccountList;
|
|
- FOrderedAccountKeysList := TList.Create;
|
|
|
|
|
|
+ FTotalChanges:=0;
|
|
|
|
+ FOrderedAccountKeysList := TPCThreadList.Create(ClassName);
|
|
if Assigned(AccountList) then begin
|
|
if Assigned(AccountList) then begin
|
|
- AccountList.FListOfOrderedAccountKeysList.Add(Self);
|
|
|
|
- if AutoAddAll then begin
|
|
|
|
- for i := 0 to AccountList.AccountsCount - 1 do begin
|
|
|
|
- AddAccountKey(AccountList.Account(i).accountInfo.accountkey);
|
|
|
|
|
|
+ Lock;
|
|
|
|
+ Try
|
|
|
|
+ AccountList.FListOfOrderedAccountKeysList.Add(Self);
|
|
|
|
+ if AutoAddAll then begin
|
|
|
|
+ for i := 0 to AccountList.AccountsCount - 1 do begin
|
|
|
|
+ AddAccountKey(AccountList.Account(i).accountInfo.accountkey);
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
@@ -4426,18 +4529,18 @@ begin
|
|
inherited;
|
|
inherited;
|
|
end;
|
|
end;
|
|
|
|
|
|
-function TOrderedAccountKeysList.Find(const AccountKey: TAccountKey; var Index: Integer): Boolean;
|
|
|
|
|
|
+function TOrderedAccountKeysList.Find(lockedList : TList; const AccountKey: TAccountKey; var Index: Integer): Boolean;
|
|
var L, H, I, C: Integer;
|
|
var L, H, I, C: Integer;
|
|
rak : TRawBytes;
|
|
rak : TRawBytes;
|
|
begin
|
|
begin
|
|
Result := False;
|
|
Result := False;
|
|
rak := TAccountComp.AccountKey2RawString(AccountKey);
|
|
rak := TAccountComp.AccountKey2RawString(AccountKey);
|
|
L := 0;
|
|
L := 0;
|
|
- H := FOrderedAccountKeysList.Count - 1;
|
|
|
|
|
|
+ H := lockedList.Count - 1;
|
|
while L <= H do
|
|
while L <= H do
|
|
begin
|
|
begin
|
|
I := (L + H) shr 1;
|
|
I := (L + H) shr 1;
|
|
- C := CompareStr( POrderedAccountKeyList(FOrderedAccountKeysList[I]).rawaccountkey, rak );
|
|
|
|
|
|
+ C := TBaseType.BinStrComp( POrderedAccountKeyList(lockedList[I]).rawaccountkey, rak );
|
|
if C < 0 then L := I + 1 else
|
|
if C < 0 then L := I + 1 else
|
|
begin
|
|
begin
|
|
H := I - 1;
|
|
H := I - 1;
|
|
@@ -4451,52 +4554,112 @@ begin
|
|
Index := L;
|
|
Index := L;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TOrderedAccountKeysList.GetAccountKeyChanges(index : Integer): Integer;
|
|
|
|
+var lockedList : TList;
|
|
|
|
+begin
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ Result := POrderedAccountKeyList(lockedList[index])^.changes_counter;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
function TOrderedAccountKeysList.GetAccountKey(index: Integer): TAccountKey;
|
|
function TOrderedAccountKeysList.GetAccountKey(index: Integer): TAccountKey;
|
|
Var raw : TRawBytes;
|
|
Var raw : TRawBytes;
|
|
|
|
+ lockedList : TList;
|
|
begin
|
|
begin
|
|
- raw := POrderedAccountKeyList(FOrderedAccountKeysList[index]).rawaccountkey;
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ raw := POrderedAccountKeyList(lockedList[index]).rawaccountkey;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
Result := TAccountComp.RawString2Accountkey(raw);
|
|
Result := TAccountComp.RawString2Accountkey(raw);
|
|
end;
|
|
end;
|
|
|
|
|
|
function TOrderedAccountKeysList.GetAccountKeyList(index: Integer): TOrderedCardinalList;
|
|
function TOrderedAccountKeysList.GetAccountKeyList(index: Integer): TOrderedCardinalList;
|
|
|
|
+var lockedList : TList;
|
|
begin
|
|
begin
|
|
- Result := POrderedAccountKeyList(FOrderedAccountKeysList[index]).accounts_number;
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ Result := POrderedAccountKeyList(lockedList[index]).accounts_number;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function TOrderedAccountKeysList.IndexOfAccountKey(const AccountKey: TAccountKey): Integer;
|
|
function TOrderedAccountKeysList.IndexOfAccountKey(const AccountKey: TAccountKey): Integer;
|
|
|
|
+var lockedList : TList;
|
|
|
|
+begin
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ If Not Find(lockedList,AccountKey,Result) then Result := -1;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+procedure TOrderedAccountKeysList.ClearAccountKeyChanges;
|
|
|
|
+var i : Integer;
|
|
|
|
+ lockedList : TList;
|
|
begin
|
|
begin
|
|
- If Not Find(AccountKey,Result) then Result := -1;
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ for i:=0 to lockedList.Count-1 do begin
|
|
|
|
+ POrderedAccountKeyList(lockedList[i])^.changes_counter:=0;
|
|
|
|
+ end;
|
|
|
|
+ FTotalChanges:=0;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TOrderedAccountKeysList.RemoveAccounts(const AccountKey: TAccountKey; const accounts: array of Cardinal);
|
|
procedure TOrderedAccountKeysList.RemoveAccounts(const AccountKey: TAccountKey; const accounts: array of Cardinal);
|
|
Var P : POrderedAccountKeyList;
|
|
Var P : POrderedAccountKeyList;
|
|
i,j : Integer;
|
|
i,j : Integer;
|
|
|
|
+ lockedList : TList;
|
|
begin
|
|
begin
|
|
- if Not Find(AccountKey,i) then exit; // Nothing to do
|
|
|
|
- P := POrderedAccountKeyList(FOrderedAccountKeysList[i]);
|
|
|
|
- for j := Low(accounts) to High(accounts) do begin
|
|
|
|
- P^.accounts_number.Remove(accounts[j]);
|
|
|
|
- end;
|
|
|
|
- if (P^.accounts_number.Count=0) And (FAutoAddAll) then begin
|
|
|
|
- // Remove from list
|
|
|
|
- FOrderedAccountKeysList.Delete(i);
|
|
|
|
- // Free it
|
|
|
|
- P^.accounts_number.free;
|
|
|
|
- Dispose(P);
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ if Not Find(lockedList,AccountKey,i) then exit; // Nothing to do
|
|
|
|
+ P := POrderedAccountKeyList(lockedList[i]);
|
|
|
|
+ inc(P^.changes_counter);
|
|
|
|
+ inc(FTotalChanges);
|
|
|
|
+ for j := Low(accounts) to High(accounts) do begin
|
|
|
|
+ P^.accounts_number.Remove(accounts[j]);
|
|
|
|
+ end;
|
|
|
|
+ if (P^.accounts_number.Count=0) And (FAutoAddAll) then begin
|
|
|
|
+ // Remove from list
|
|
|
|
+ lockedList.Delete(i);
|
|
|
|
+ // Free it
|
|
|
|
+ P^.accounts_number.free;
|
|
|
|
+ Dispose(P);
|
|
|
|
+ end;
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TOrderedAccountKeysList.RemoveAccountKey(const AccountKey: TAccountKey);
|
|
procedure TOrderedAccountKeysList.RemoveAccountKey(const AccountKey: TAccountKey);
|
|
Var P : POrderedAccountKeyList;
|
|
Var P : POrderedAccountKeyList;
|
|
i,j : Integer;
|
|
i,j : Integer;
|
|
|
|
+ lockedList : TList;
|
|
begin
|
|
begin
|
|
- if Not Find(AccountKey,i) then exit; // Nothing to do
|
|
|
|
- P := POrderedAccountKeyList(FOrderedAccountKeysList[i]);
|
|
|
|
- // Remove from list
|
|
|
|
- FOrderedAccountKeysList.Delete(i);
|
|
|
|
- // Free it
|
|
|
|
- P^.accounts_number.free;
|
|
|
|
- Dispose(P);
|
|
|
|
|
|
+ lockedList := Lock;
|
|
|
|
+ Try
|
|
|
|
+ if Not Find(lockedList,AccountKey,i) then exit; // Nothing to do
|
|
|
|
+ P := POrderedAccountKeyList(lockedList[i]);
|
|
|
|
+ inc(P^.changes_counter);
|
|
|
|
+ inc(FTotalChanges);
|
|
|
|
+ // Remove from list
|
|
|
|
+ lockedList.Delete(i);
|
|
|
|
+ // Free it
|
|
|
|
+ P^.accounts_number.free;
|
|
|
|
+ Dispose(P);
|
|
|
|
+ finally
|
|
|
|
+ Unlock;
|
|
|
|
+ end;
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TAccountPreviousBlockInfo }
|
|
{ TAccountPreviousBlockInfo }
|