瀏覽代碼

TOpReference value

As described on PIP-0015, this value will return a 64bits with "Account" and "N_Operation" data
PascalCoin 6 年之前
父節點
當前提交
07e764d948
共有 1 個文件被更改,包括 173 次插入1 次删除
  1. 173 1
      src/core/UBlockChain.pas

+ 173 - 1
src/core/UBlockChain.pas

@@ -191,6 +191,24 @@ Type
     Property OperationResume[index : Integer] : TOperationResume read GetOperationResume; default;
   End;
 
+  TOpReference = UInt64;
+  TOrderedOpReferenceList = Class
+    FList : TList;
+  private
+    function FindOpReference(AOpReference : TOpReference; var Index: Integer): Boolean;
+    function FindAccount(AAccount : Cardinal; var Index: Integer): Boolean;
+  public
+    Constructor Create;
+    Destructor Destroy; override;
+    function IndexOf(AOpReference : TOpReference) : Integer; overload;
+    function IndexOfAccount(AAccount : Cardinal) : Integer;
+    function Get(AIndex : Integer) : TOpReference;
+    function Count: Integer;
+    procedure Delete(AIndex : Integer);
+    procedure Clear;
+    function Add(AOpReference : TOpReference) : Integer;
+  End;
+
   { TPCOperation }
 
   TPCOperation = Class
@@ -245,6 +263,7 @@ Type
     Class function FinalOperationHashAsHexa(Const operationHash : TRawBytes) : AnsiString;
     class function OperationHashAsHexa(const operationHash : TRawBytes) : AnsiString;
     function Sha256 : TRawBytes;
+    function GetOpReference : TOpReference;
   End;
 
   { TOperationsHashTree }
@@ -253,6 +272,7 @@ Type
   private
     FListOrderedByAccountsData : TList;
     FListOrderedBySha256 : TList; // Improvement TOperationsHashTree speed 2.1.6
+    FListOrderedByOpReference : TOrderedOpReferenceList;
     FHashTreeOperations : TPCThreadList; // Improvement TOperationsHashTree speed 2.1.6
     FHashTree: TRawBytes;
     FOnChanged: TNotifyEvent;
@@ -1753,6 +1773,7 @@ begin
       l.Clear;
       FListOrderedBySha256.Clear;
       FListOrderedByAccountsData.Clear;
+      FListOrderedByOpReference.Clear;
       FHashTree := '';
     End;
     If Assigned(FOnChanged) then FOnChanged(Self);
@@ -1802,6 +1823,7 @@ begin
   FOnChanged:=Nil;
   FListOrderedBySha256 := TList.Create;
   FListOrderedByAccountsData := TList.Create;
+  FListOrderedByOpReference := TOrderedOpReferenceList.Create;
   FTotalAmount := 0;
   FTotalFee := 0;
   FHashTree := '';
@@ -1817,7 +1839,10 @@ begin
   l := FHashTreeOperations.LockList;
   try
     P := l[index];
-
+    // Delete from Ordered by OpReference
+    if Not FListOrderedByOpReference.FindOpReference(P^.Op.GetOpReference,i) then begin
+      TLog.NewLog(ltError,ClassName,'DEV ERROR 20180629-1 Operation not found in ordered by reference list: '+P^.Op.ToString);
+    end else FListOrderedByOpReference.Delete(i);
     // Delete from Ordered
     If Not FindOrderedBySha(l,P^.Op.Sha256,iDel) then begin
       TLog.NewLog(ltError,ClassName,'DEV ERROR 20180213-1 Operation not found in ordered list: '+P^.Op.ToString);
@@ -1872,6 +1897,7 @@ begin
   SetLength(FHashTree,0);
   FreeAndNil(FListOrderedBySha256);
   FreeAndNil(FListOrderedByAccountsData);
+  FreeAndNil(FListOrderedByOpReference);
   inherited;
 end;
 
@@ -1996,6 +2022,7 @@ begin
       TCrypto.DoSha256(h,FHashTree);
     end;
     npos := list.Add(P);
+    FListOrderedByOpReference.Add(op.GetOpReference);
     // Improvement: Will allow to add duplicate Operations, so add only first to orderedBySha
     If Not FindOrderedBySha(list,op.Sha256,i) then begin
       // Protection: Will add only once
@@ -2320,6 +2347,15 @@ begin
   end else Raise Exception.Create('ERROR DEV 20170426-1'); // This should never happen, if good coded
 end;
 
+function TPCOperation.GetOpReference: TOpReference;
+  // XXXXXXXXX
+  // Described on PIP-0015 by Herman Schoenfeld
+  // Will return a 64 bit value composed by SignerAccount (first 4 bytes) and n_Operation (last 4 bytes)
+  // Will allow to quick search an Operation in a TOperationsHashTree object
+begin
+  Result := ((UInt64(SignerAccount) SHL 32) OR UInt64(N_Operation));
+end;
+
 procedure TPCOperation.SignerAccounts(list: TList);
 begin
   list.Clear;
@@ -2792,6 +2828,142 @@ begin
   end;
 end;
 
+{ TOrderedOpReferenceList }
+
+{$UNDEF IS64BITS}
+{$IFDEF CPU64BITS}{$DEFINE IS64BITS}{$ENDIF}
+{$IFDEF FPC}{$IFDEF CPU64}{$DEFINE IS64BITS}{$ENDIF}{$ENDIF}
+{$IFNDEF IS64BITS}
+Type POpReference = ^TOpReference;
+{$ENDIF}
+
+function TOrderedOpReferenceList.Add(AOpReference: TOpReference) : Integer;
+  {$IFNDEF IS64BITS}
+var p : POpReference;
+  {$ENDIF}
+begin
+  FindOpReference(AOpReference,Result);
+  // Will allow duplicates
+  {$IFNDEF IS64BITS}
+  new(p);
+  p^ := AOpReference;
+  FList.Insert(Result,p);
+  {$ELSE}
+  FList.Insert(Result,TObject(AOpReference));
+  {$ENDIF}
+end;
+
+procedure TOrderedOpReferenceList.Clear;
+Var i : Integer;
+  {$IFNDEF IS64BITS}
+  p : POpReference;
+  {$ENDIF}
+begin
+  {$IFNDEF IS64BITS}
+  for i := 0 to FList.Count-1 do begin
+    p := FList[i];
+    Dispose(p);
+  end;
+  {$ENDIF}
+  FList.Clear;
+end;
+
+function TOrderedOpReferenceList.Count: Integer;
+begin
+  Result := FList.Count;
+end;
+
+constructor TOrderedOpReferenceList.Create;
+begin
+  FList := TList.Create;
+end;
+
+procedure TOrderedOpReferenceList.Delete(AIndex: Integer);
+  {$IFNDEF IS64BITS}
+var p : POpReference;
+  {$ENDIF}
+begin
+  {$IFNDEF IS64BITS}
+  p := FList[AIndex];
+  Dispose(p);
+  {$ENDIF}
+  FList.Delete(AIndex);
+end;
+
+destructor TOrderedOpReferenceList.Destroy;
+begin
+  Clear;
+  FreeAndNil(FList);
+  inherited;
+end;
+
+function TOrderedOpReferenceList.FindAccount(AAccount: Cardinal; var Index: Integer): Boolean;
+var
+  cCurrent : TOpReference;
+begin
+  Result := FindOpReference((AAccount SHL 32),Index);
+  if (Not Result) And (Index<FList.Count) then begin
+    // Check if Index is same AAccount value
+    {$IFNDEF IS64BITS}
+    cCurrent := POpReference( FList[Index] )^;
+    {$ELSE}
+    cCurrent := TOpReference(FList[Index]);
+    {$ENDIF}
+    if (cCurrent SHR 32)=AAccount then Result := True;
+  end;
+end;
+
+function TOrderedOpReferenceList.FindOpReference(AOpReference: TOpReference; var Index: Integer): Boolean;
+var L, H, I: Integer;
+  cCurrent : TOpReference;
+  C : Int64;
+begin
+  Result := False;
+  L := 0;
+  H := FList.Count - 1;
+  while L <= H do
+  begin
+    I := (L + H) shr 1;
+    // Capture value
+    {$IFNDEF IS64BITS}
+    cCurrent := POpReference( FList[I] )^;
+    {$ELSE}
+    cCurrent := TOpReference(FList[I]);
+    {$ENDIF}
+
+    C := Int64(cCurrent) - Int64(AOpReference);
+    if C < 0 then L := I + 1 else
+    begin
+      H := I - 1;
+      if C = 0 then
+      begin
+        Result := True;
+        L := I;
+      end;
+    end;
+  end;
+  Index := L;
+end;
+
+function TOrderedOpReferenceList.Get(AIndex: Integer): TOpReference;
+begin
+  {$IFNDEF IS64BITS}
+  Result := POpReference( FList[AIndex] )^;
+  {$ELSE}
+  Result := TOpReference(FList[AIndex]);
+  {$ENDIF}
+end;
+
+function TOrderedOpReferenceList.IndexOf(AOpReference: TOpReference): Integer;
+begin
+  if Not FindOpReference(AOpReference,Result) then Result := -1;
+end;
+
+function TOrderedOpReferenceList.IndexOfAccount(AAccount: Cardinal): Integer;
+begin
+  if Not FindAccount(AAccount,Result) then Result := -1;
+end;
+
 initialization
   SetLength(_OperationsClass, 0);
   RegisterOperationsClass;