Browse Source

Add "id" 16 bytes field (GUID/UUID) as described on PIP-0016

PascalCoin 6 years ago
parent
commit
39f139696a
5 changed files with 68 additions and 28 deletions
  1. 9 4
      README.md
  2. 30 0
      src/core/UAccounts.pas
  3. 1 3
      src/core/UBlockChain.pas
  4. 20 11
      src/core/UOpTransaction.pas
  5. 8 10
      src/core/URPC.pas

+ 9 - 4
README.md

@@ -40,10 +40,11 @@ Also, consider a donation at PascalCoin development account: "0-10"
   - Atomic Swaps can be executed ONLY during the locking period specified
   - Atomic Swaps can be executed ONLY during the locking period specified
 - Implementation of PIP-0030 (Safebox root) -> https://github.com/PascalCoin/PascalCoin/blob/master/PIP/PIP-0030.md
 - Implementation of PIP-0030 (Safebox root) -> https://github.com/PascalCoin/PascalCoin/blob/master/PIP/PIP-0030.md
 - Implementation of PIP-0029 (Account Seals) -> https://github.com/PascalCoin/PascalCoin/blob/master/PIP/PIP-0029.md
 - Implementation of PIP-0029 (Account Seals) -> https://github.com/PascalCoin/PascalCoin/blob/master/PIP/PIP-0029.md
-- New digest hash value for OP_DATA ( PIP-0016 ) on Protocol 5
+- Updated "OP_DATA" operation: (PIP-0016)
+  - New digest hash value for OP_DATA ( PIP-0016 ) on Protocol 5
+  - Added "id" field (GUID/UUID type as described on PIP-0016), was missing on V4, added on V5
 - Hardcoded RandomHash digest/hash values for quick speed safebox check on fresh installation
 - Hardcoded RandomHash digest/hash values for quick speed safebox check on fresh installation
-- JSON-RPC changes:
-  - Updated ""
+- JSON-RPC changes:  
   - Updated "listaccountforsale" call to allow ATOMIC SWAPS (PIP-0032)
   - Updated "listaccountforsale" call to allow ATOMIC SWAPS (PIP-0032)
     - Added "type" to discrimine between kind of listing. Available values are:
     - Added "type" to discrimine between kind of listing. Available values are:
       - "public_sale"
       - "public_sale"
@@ -58,6 +59,11 @@ Also, consider a donation at PascalCoin development account: "0-10"
 	- "amount_to_swap" : (PASCURRENCY) amount that will be transferred to counterparty account on ATOMIC COIN SWAP ("receiver_swap_account")
 	- "amount_to_swap" : (PASCURRENCY) amount that will be transferred to counterparty account on ATOMIC COIN SWAP ("receiver_swap_account")
 	- "receiver_swap_account": (Integer) Counterpaty account that will receive "amount_to_swap" on ATOMIC COIN SWAP
 	- "receiver_swap_account": (Integer) Counterpaty account that will receive "amount_to_swap" on ATOMIC COIN SWAP
   - Updated "Operation Object" return values:
   - Updated "Operation Object" return values:
+    - "senders" : ARRAY
+      - "data" : OBJECT will store OP_DATA information when operation is OP_DATA type as described on PIP-0016
+        - "id" : (String) String representation of GUID/UUID as "00000000-0000-0000-0000-000000000000" that stores 16 bytes
+        - "sequence" : (Integer)
+        - "type" : (Integer)
     - "changers" : ARRAY
     - "changers" : ARRAY
       - "new_data" : (HEXASTRING) : If "data" is changed on "account"
       - "new_data" : (HEXASTRING) : If "data" is changed on "account"
       - "changes" : (String) Description of changes type made
       - "changes" : (String) Description of changes type made
@@ -66,7 +72,6 @@ TODO
 - TODO Implement Seal calculation
 - TODO Implement Seal calculation
 - TODO: RPC calls for PIP-0030
 - TODO: RPC calls for PIP-0030
 - TODO: RPC calls for PIP-0016
 - TODO: RPC calls for PIP-0016
-- TODO: Save data for GUID on OPDATA operation and use GUID for calcs
 
 
 ### Build 4.0.3.1 - 2019-04-12
 ### Build 4.0.3.1 - 2019-04-12
 - Fixed core bug #182 in RPC calls
 - Fixed core bug #182 in RPC calls

+ 30 - 0
src/core/UAccounts.pas

@@ -501,6 +501,8 @@ Type
     class Function ReadAccountKey(Stream: TStream; var value : TAccountKey): Integer;
     class Function ReadAccountKey(Stream: TStream; var value : TAccountKey): Integer;
     class Function SaveStreamToRaw(Stream: TStream) : TRawBytes;
     class Function SaveStreamToRaw(Stream: TStream) : TRawBytes;
     class procedure LoadStreamFromRaw(Stream: TStream; const raw : TRawBytes);
     class procedure LoadStreamFromRaw(Stream: TStream; const raw : TRawBytes);
+    class Function WriteGUID(AStream : TStream; const AGUID : TGUID) : Integer;
+    class Function ReadGUID(AStream : TStream; var AGUID : TGUID) : Integer;
   End;
   End;
 
 
 
 
@@ -1086,6 +1088,22 @@ begin
 end;
 end;
 
 
 
 
+class function TStreamOp.ReadGUID(AStream: TStream; var AGUID: TGUID): Integer;
+var i : Integer;
+begin
+  if AStream.Size - AStream.Position < 16 then begin
+    Result := 0; // Not enough space!
+    Exit;
+  end;
+  AStream.Read(AGUID.D1,4);
+  AStream.Read(AGUID.D2,2);
+  AStream.Read(AGUID.D3,2);
+  for i := 0 to 7 do begin
+    AStream.Read(AGUID.D4[i],1);
+  end;
+  Result := 16; // GUID is 16 bytes
+end;
+
 class function TStreamOp.ReadString(Stream: TStream; var value: String): Integer;
 class function TStreamOp.ReadString(Stream: TStream; var value: String): Integer;
 var raw : TRawBytes;
 var raw : TRawBytes;
 begin
 begin
@@ -1122,6 +1140,18 @@ begin
 end;
 end;
 
 
 
 
+class function TStreamOp.WriteGUID(AStream: TStream; const AGUID: TGUID): Integer;
+var i : Integer;
+begin
+  AStream.Write(AGUID.D1,4);
+  AStream.Write(AGUID.D2,2);
+  AStream.Write(AGUID.D3,2);
+  for i := 0 to 7 do begin
+    AStream.Write(AGUID.D4[i],1);
+  end;
+  Result := 16; // GUID is 16 bytes
+end;
+
 { TAccountComp }
 { TAccountComp }
 Const CT_Base58 : String = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
 Const CT_Base58 : String = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
 
 

+ 1 - 3
src/core/UBlockChain.pas

@@ -126,7 +126,7 @@ Type
     Account : Cardinal;
     Account : Cardinal;
     Amount : Int64;
     Amount : Int64;
     N_Operation : Cardinal;
     N_Operation : Cardinal;
-    Data : TMultiOpData;
+    OpData : TMultiOpData; // Filled only when Operation is TOpData type
     Payload : TRawBytes;
     Payload : TRawBytes;
     Signature : TECDSA_SIG;
     Signature : TECDSA_SIG;
   end;
   end;
@@ -134,7 +134,6 @@ Type
   TMultiOpReceiver = Record
   TMultiOpReceiver = Record
     Account : Cardinal;
     Account : Cardinal;
     Amount : Int64;
     Amount : Int64;
-    Data : TMultiOpData;
     Payload : TRawBytes;
     Payload : TRawBytes;
   end;
   end;
   TMultiOpReceivers = Array of TMultiOpReceiver;
   TMultiOpReceivers = Array of TMultiOpReceiver;
@@ -150,7 +149,6 @@ Type
     Account_Price : Int64;
     Account_Price : Int64;
     Locked_Until_Block : Cardinal;
     Locked_Until_Block : Cardinal;
     Hashed_secret : TRawBytes;
     Hashed_secret : TRawBytes;
-    Data : TMultiOpData;
     Fee: Int64;
     Fee: Int64;
     Signature: TECDSA_SIG;
     Signature: TECDSA_SIG;
   end;
   end;

+ 20 - 11
src/core/UOpTransaction.pas

@@ -316,6 +316,7 @@ Type
     account_sender,              // The account sender. Public key must be EQUAL to account_signer public key
     account_sender,              // The account sender. Public key must be EQUAL to account_signer public key
     account_target: Cardinal;    // The destination account. Will recive DATA and amount (if any)
     account_target: Cardinal;    // The destination account. Will recive DATA and amount (if any)
     n_operation : Cardinal;      // Signer n_operation
     n_operation : Cardinal;      // Signer n_operation
+    guid: TGUID;                 // GUID value, added on Protocol V5
     dataType : Word;             // 2 byte data type
     dataType : Word;             // 2 byte data type
     dataSequence : Word;         // 2 byte data sequence
     dataSequence : Word;         // 2 byte data sequence
     amount: UInt64;              // Allow amount=0
     amount: UInt64;              // Allow amount=0
@@ -355,7 +356,7 @@ Type
   End;
   End;
 
 
 Const
 Const
-  CT_TOpDataData_NUL : TOpDataData = (account_signer:0;account_sender:0;account_target:0;n_operation:0;dataType:0;dataSequence:0;amount:0;fee:0;payload:Nil;sign:(r:Nil;s:Nil));
+  CT_TOpDataData_NUL : TOpDataData = (account_signer:0;account_sender:0;account_target:0;n_operation:0;guid:(D1:0;D2:0;D3:0;D4:(0,0,0,0,0,0,0,0));dataType:0;dataSequence:0;amount:0;fee:0;payload:Nil;sign:(r:Nil;s:Nil));
 
 
 Procedure RegisterOperationsClass;
 Procedure RegisterOperationsClass;
 
 
@@ -2470,6 +2471,10 @@ begin
   Stream.Write(FData.account_sender,Sizeof(FData.account_sender));
   Stream.Write(FData.account_sender,Sizeof(FData.account_sender));
   Stream.Write(FData.account_target,Sizeof(FData.account_target));
   Stream.Write(FData.account_target,Sizeof(FData.account_target));
   Stream.Write(FData.n_operation,Sizeof(FData.n_operation));
   Stream.Write(FData.n_operation,Sizeof(FData.n_operation));
+  // VERSION 5: write the GUID
+  if FProtocolVersion >= CT_PROTOCOL_5 then begin
+    TStreamOp.writeGuid(Stream,FData.guid);
+  end;
   Stream.Write(FData.dataType,Sizeof(FData.dataType));
   Stream.Write(FData.dataType,Sizeof(FData.dataType));
   Stream.Write(FData.dataSequence,Sizeof(FData.dataSequence));
   Stream.Write(FData.dataSequence,Sizeof(FData.dataSequence));
   Stream.Write(FData.amount,Sizeof(FData.amount));
   Stream.Write(FData.amount,Sizeof(FData.amount));
@@ -2483,11 +2488,16 @@ end;
 function TOpData.LoadOpFromStream(Stream: TStream; LoadExtendedData: Boolean): Boolean;
 function TOpData.LoadOpFromStream(Stream: TStream; LoadExtendedData: Boolean): Boolean;
 begin
 begin
   Result := false;
   Result := false;
-  if Stream.Size-Stream.Position < 36  then exit; // Invalid stream
+  if Stream.Size-Stream.Position < 16  then exit; // Invalid stream
   Stream.Read(FData.account_signer,Sizeof(FData.account_signer));
   Stream.Read(FData.account_signer,Sizeof(FData.account_signer));
   Stream.Read(FData.account_sender,Sizeof(FData.account_sender));
   Stream.Read(FData.account_sender,Sizeof(FData.account_sender));
   Stream.Read(FData.account_target,Sizeof(FData.account_target));
   Stream.Read(FData.account_target,Sizeof(FData.account_target));
   Stream.Read(FData.n_operation,Sizeof(FData.n_operation));
   Stream.Read(FData.n_operation,Sizeof(FData.n_operation));
+  // VERSION 5: write the GUID
+  if FProtocolVersion >= CT_PROTOCOL_5 then begin
+    if TStreamOp.ReadGUID(Stream,FData.guid)<16 then Exit;
+  end;
+  if Stream.Size-Stream.Position < 20  then exit; // Invalid stream
   Stream.Read(FData.dataType,Sizeof(FData.dataType));
   Stream.Read(FData.dataType,Sizeof(FData.dataType));
   Stream.Read(FData.dataSequence,Sizeof(FData.dataSequence));
   Stream.Read(FData.dataSequence,Sizeof(FData.dataSequence));
   Stream.Read(FData.amount,Sizeof(FData.amount));
   Stream.Read(FData.amount,Sizeof(FData.amount));
@@ -2521,9 +2531,6 @@ begin
     OperationResume.Senders[0].N_Operation:=FData.n_operation;
     OperationResume.Senders[0].N_Operation:=FData.n_operation;
     OperationResume.Senders[0].Signature:=FData.sign;
     OperationResume.Senders[0].Signature:=FData.sign;
     OperationResume.Senders[0].Amount:=Int64(FData.amount + FData.fee)*(-1);
     OperationResume.Senders[0].Amount:=Int64(FData.amount + FData.fee)*(-1);
-    OperationResume.Senders[0].Data.ID := StringToGUID('{00000000-0000-0000-0000-000000000000}'); // NOTE: ID missing in V4, added to V5
-    OperationResume.Senders[0].Data.Sequence := FData.dataSequence;
-    OperationResume.Senders[0].Data.&Type := FData.dataType;
   end else begin
   end else begin
     OperationResume.Senders[0].Amount:=Int64(FData.amount)*(-1);
     OperationResume.Senders[0].Amount:=Int64(FData.amount)*(-1);
     SetLength(OperationResume.Changers,1);
     SetLength(OperationResume.Changers,1);
@@ -2532,9 +2539,6 @@ begin
     OperationResume.Changers[0].Fee:=FData.fee;
     OperationResume.Changers[0].Fee:=FData.fee;
     OperationResume.Changers[0].N_Operation:=FData.n_operation;
     OperationResume.Changers[0].N_Operation:=FData.n_operation;
     OperationResume.Changers[0].Signature:=FData.sign;
     OperationResume.Changers[0].Signature:=FData.sign;
-    OperationResume.Senders[0].Data.ID := StringToGUID('{00000000-0000-0000-0000-000000000000}'); // NOTE: ID missing in V4, added to V5
-    OperationResume.Changers[0].Data.Sequence := FData.dataSequence;
-    OperationResume.Changers[0].Data.&Type := FData.dataType;
   end;
   end;
   //
   //
   SetLength(OperationResume.Receivers,1);
   SetLength(OperationResume.Receivers,1);
@@ -2542,9 +2546,10 @@ begin
   OperationResume.Receivers[0].Account:=FData.account_target;
   OperationResume.Receivers[0].Account:=FData.account_target;
   OperationResume.Receivers[0].Amount:=FData.amount;
   OperationResume.Receivers[0].Amount:=FData.amount;
   OperationResume.Receivers[0].Payload:=FData.payload;
   OperationResume.Receivers[0].Payload:=FData.payload;
-  OperationResume.Senders[0].Data.ID := StringToGUID('{00000000-0000-0000-0000-000000000000}'); // NOTE: ID missing in V4, added to V5
-  OperationResume.Receivers[0].Data.Sequence := FData.dataSequence;
-  OperationResume.Receivers[0].Data.&Type := FData.dataType;
+  // Add OpData missing in V4, added to V5
+  OperationResume.Senders[0].OpData.ID := FData.guid;
+  OperationResume.Senders[0].OpData.Sequence := FData.dataSequence;
+  OperationResume.Senders[0].OpData.&Type := FData.dataType;
 
 
   //
   //
   OperationResume.n_operation:=FData.n_operation;
   OperationResume.n_operation:=FData.n_operation;
@@ -2763,6 +2768,10 @@ begin
     Stream.Write(FData.account_sender,Sizeof(FData.account_sender));
     Stream.Write(FData.account_sender,Sizeof(FData.account_sender));
     Stream.Write(FData.account_target,Sizeof(FData.account_target));
     Stream.Write(FData.account_target,Sizeof(FData.account_target));
     Stream.Write(FData.n_operation,Sizeof(FData.n_operation));
     Stream.Write(FData.n_operation,Sizeof(FData.n_operation));
+    // VERSION 5: write the GUID to the digest
+    if current_protocol >= CT_PROTOCOL_5 then begin
+      TStreamOp.WriteGUID(Stream,FData.guid);
+    end;
     Stream.Write(FData.dataType,Sizeof(FData.dataType));
     Stream.Write(FData.dataType,Sizeof(FData.dataType));
     Stream.Write(FData.dataSequence,Sizeof(FData.dataSequence));
     Stream.Write(FData.dataSequence,Sizeof(FData.dataSequence));
     Stream.Write(FData.amount,Sizeof(FData.amount));
     Stream.Write(FData.amount,Sizeof(FData.amount));

+ 8 - 10
src/core/URPC.pas

@@ -183,13 +183,13 @@ Var i : Integer;
   jsonArr : TPCJSONArray;
   jsonArr : TPCJSONArray;
   auxObj : TPCJSONObject;
   auxObj : TPCJSONObject;
 
 
-  procedure FillDataObject(AParentObj : TPCJSONObject; const AData : TMultiOpData);
+  procedure FillOpDataObject(AParentObj : TPCJSONObject; const AOpData : TMultiOpData);
   var LDataObj : TPCJSONObject;
   var LDataObj : TPCJSONObject;
   begin
   begin
     LDataObj := AParentObj.GetAsObject('data');
     LDataObj := AParentObj.GetAsObject('data');
-    LDataObj.GetAsVariant('id').Value := AData.ID.ToString; // Note: Delphi always return with brackets
-    LDataObj.GetAsVariant('sequence').Value := AData.Sequence;
-    LDataObj.GetAsVariant('type').Value := AData.&Type;
+    LDataObj.GetAsVariant('id').Value := AOpData.ID.ToString; // Note: Delphi always return with brackets
+    LDataObj.GetAsVariant('sequence').Value := AOpData.Sequence;
+    LDataObj.GetAsVariant('type').Value := AOpData.&Type;
   end;
   end;
 
 
 Begin
 Begin
@@ -224,7 +224,7 @@ Begin
       auxObj.GetAsVariant('amount_s').Value := TAccountComp.FormatMoney (OPR.Senders[i].Amount * (-1));
       auxObj.GetAsVariant('amount_s').Value := TAccountComp.FormatMoney (OPR.Senders[i].Amount * (-1));
       auxObj.GetAsVariant('payload').Value := TCrypto.ToHexaString(OPR.Senders[i].Payload);
       auxObj.GetAsVariant('payload').Value := TCrypto.ToHexaString(OPR.Senders[i].Payload);
       if (OPR.OpType = CT_Op_Data) then begin
       if (OPR.OpType = CT_Op_Data) then begin
-        FillDataObject(auxObj, OPR.Receivers[i].Data);
+        FillOpDataObject(auxObj, OPR.senders[i].OpData);
       end;
       end;
     end;
     end;
     //
     //
@@ -235,9 +235,6 @@ Begin
       auxObj.GetAsVariant('amount').Value :=  TAccountComp.FormatMoneyDecimal(OPR.Receivers[i].Amount);
       auxObj.GetAsVariant('amount').Value :=  TAccountComp.FormatMoneyDecimal(OPR.Receivers[i].Amount);
       auxObj.GetAsVariant('amount_s').Value :=  TAccountComp.FormatMoney(OPR.Receivers[i].Amount);
       auxObj.GetAsVariant('amount_s').Value :=  TAccountComp.FormatMoney(OPR.Receivers[i].Amount);
       auxObj.GetAsVariant('payload').Value := TCrypto.ToHexaString(OPR.Receivers[i].Payload);
       auxObj.GetAsVariant('payload').Value := TCrypto.ToHexaString(OPR.Receivers[i].Payload);
-      if (OPR.OpType = CT_Op_Data) then begin
-        FillDataObject(auxObj, OPR.Receivers[i].Data);
-      end;
     end;
     end;
     jsonArr := jsonObject.GetAsArray('changers');
     jsonArr := jsonObject.GetAsArray('changers');
     for i:=Low(OPR.Changers) to High(OPR.Changers) do begin
     for i:=Low(OPR.Changers) to High(OPR.Changers) do begin
@@ -277,9 +274,10 @@ Begin
         auxObj.GetAsVariant('fee').Value := TAccountComp.FormatMoneyDecimal(OPR.Changers[i].Fee * (-1));
         auxObj.GetAsVariant('fee').Value := TAccountComp.FormatMoneyDecimal(OPR.Changers[i].Fee * (-1));
         auxObj.GetAsVariant('fee_s').Value := TAccountComp.FormatMoney(OPR.Changers[i].Fee * (-1));
         auxObj.GetAsVariant('fee_s').Value := TAccountComp.FormatMoney(OPR.Changers[i].Fee * (-1));
       end;
       end;
+      { XXXXXXXXXX
       if (OPR.OpType = CT_Op_Data) then begin
       if (OPR.OpType = CT_Op_Data) then begin
-        FillDataObject(auxObj, OPR.Changers[i].Data);
-      end;
+        FillDataObject(auxObj, OPR.Changers[i].OpData);
+      end;        }
       LString := '';
       LString := '';
       for LOpChangeAccountInfoType := Low(LOpChangeAccountInfoType) to High(LOpChangeAccountInfoType) do begin
       for LOpChangeAccountInfoType := Low(LOpChangeAccountInfoType) to High(LOpChangeAccountInfoType) do begin
         if (LOpChangeAccountInfoType in OPR.Changers[i].Changes_type) then begin
         if (LOpChangeAccountInfoType in OPR.Changers[i].Changes_type) then begin