Browse Source

PIP-0029 and PIP-024 Source core initial implementation

Added initial value needed for PIP-0029
TODO: Need to add Account.seal calculation based on PIP-0029 specifications
TODO: Need to add PIP-0024 operations
PascalCoin 6 years ago
parent
commit
da72a70f60
4 changed files with 129 additions and 30 deletions
  1. 7 1
      README.md
  2. 78 26
      src/core/UAccounts.pas
  3. 32 0
      src/core/UBaseTypes.pas
  4. 12 3
      src/core/UNetProtocol.pas

+ 7 - 1
README.md

@@ -37,8 +37,14 @@ Also, consider a donation at PascalCoin development account: "0-10"
 ### Current Build (Pending release date)
 - Upgrade to Protocol 5 (Hard fork)
 - Implementation of PIP-0030 -> https://github.com/PascalCoin/PascalCoin/blob/master/PIP/PIP-0030.md
+- Implementation of PIP-0029 -> https://github.com/PascalCoin/PascalCoin/blob/master/PIP/PIP-0029.md
 - New digest hash value for OP_DATA ( PIP-0016 ) on Protocol 5
-
+TODO  
+- TODO: RPC calls for PIP-0029
+- TODO Implement Seal calculation
+- TODO: RPC calls for PIP-0030
+- 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
 - Fixed core bug #182 in RPC calls

+ 78 - 26
src/core/UAccounts.pas

@@ -87,6 +87,8 @@ Type
     n_operation: Cardinal;    // count number of owner operations (when receive, this is not updated)
     name : TRawBytes;         // Protocol 2. Unique name
     account_type : Word;      // Protocol 2. Layer 2 use case
+    account_data : TRawBytes; // Protocol 5. PIP-0024 RAW data information
+    account_seal : TRawBytes;  // Protocol 5. PIP-0029 seal of data changes
     previous_updated_block : Cardinal; // New Build 1.0.8 -> Only used to store this info to storage. It helps App to search when an account was updated. NOT USED FOR HASH CALCULATIONS!
   End;
   PAccount = ^TAccount;
@@ -150,7 +152,7 @@ Type
     Class Function AccountBlock(Const account_number : Cardinal) : Cardinal;
     Class Function AccountInfo2RawString(const AccountInfo : TAccountInfo) : TRawBytes; overload;
     Class procedure AccountInfo2RawString(const AccountInfo : TAccountInfo; var dest : TRawBytes); overload;
-    Class procedure SaveAccountToAStream(Stream: TStream; const Account : TAccount);
+    Class procedure SaveAccountToAStream(Stream: TStream; const Account : TAccount; current_protocol : Word);
     Class function LoadAccountFromStream(Stream: TStream; var Account : TAccount) : Boolean;
     Class Function RawString2AccountInfo(const rawaccstr: TRawBytes): TAccountInfo; overload;
     Class procedure RawString2AccountInfo(const rawaccstr: TRawBytes; var dest : TAccountInfo); overload;
@@ -280,8 +282,10 @@ Type
     procedure SearchBlockWhenOnSeparatedChain(blockNumber : Cardinal; out blockAccount : TBlockAccount);
   protected
     FTotalFee: Int64;
-    Procedure UpdateAccount(account_number : Cardinal; const newAccountInfo: TAccountInfo; const newName : TRawBytes; newType : Word; newBalance: UInt64; newN_operation: Cardinal;
-              accountUpdateStyle : TAccountUpdateStyle; newUpdated_block, newPrevious_Updated_block : Cardinal);
+    Procedure UpdateAccount(account_number : Cardinal; const newAccountInfo: TAccountInfo; const newName : TRawBytes; newType : Word;
+         newBalance: UInt64; newN_operation: Cardinal;
+         const newAccountData, newAccountSeal : TRawBytes;
+         accountUpdateStyle : TAccountUpdateStyle; newUpdated_block, newPrevious_Updated_block : Cardinal);
     Function AddNew(Const blockChain : TOperationBlock) : TBlockAccount;
     function DoUpgradeToProtocol2 : Boolean;
     function DoUpgradeToProtocol3 : Boolean;
@@ -295,7 +299,7 @@ Type
     function AccountsCount: Integer;
     Function BlocksCount : Integer;
     Procedure CopyFrom(accounts : TPCSafeBox);
-    Class Function CalcBlockHash(const block : TBlockAccount; useProtocol2Method : Boolean):TRawBytes;
+    Class Function CalcBlockHash(const block : TBlockAccount; current_protocol : Word):TRawBytes;
     Class Function BlockAccountToText(Const block : TBlockAccount):String;
     Function LoadSafeBoxFromStream(Stream : TStream; checkAll : Boolean; var LastReadBlock : TBlockAccount; var errors : String) : Boolean; overload;
     Function LoadSafeBoxFromStream(Stream : TStream; checkAll : Boolean; checkSafeboxHash : TRawBytes; progressNotify : TProgressNotify; previousCheckedSafebox : TPCSafebox; var LastReadBlock : TBlockAccount; var errors : String) : Boolean; overload;
@@ -457,16 +461,16 @@ Const
   CT_OperationBlock_NUL : TOperationBlock = (block:0;account_key:(EC_OpenSSL_NID:0;x:Nil;y:Nil);reward:0;fee:0;protocol_version:0;
     protocol_available:0;timestamp:0;compact_target:0;nonce:0;block_payload:Nil;initial_safe_box_hash:Nil;operations_hash:Nil;proof_of_work:Nil);
   CT_AccountInfo_NUL : TAccountInfo = (state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));
-  CT_Account_NUL : TAccount = (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;previous_updated_block:0);
+  CT_Account_NUL : TAccount = (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;account_data:Nil;account_seal:Nil;previous_updated_block:0);
   CT_BlockAccount_NUL : TBlockAccount = (
     blockchainInfo:(block:0;account_key:(EC_OpenSSL_NID:0;x:Nil;y:Nil);reward:0;fee:0;protocol_version:0;
     protocol_available:0;timestamp:0;compact_target:0;nonce:0;block_payload:Nil;initial_safe_box_hash:Nil;operations_hash:Nil;proof_of_work:Nil);
     accounts:(
-    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;previous_updated_block:0),
-    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;previous_updated_block:0),
-    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;previous_updated_block:0),
-    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;previous_updated_block:0),
-    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;previous_updated_block:0)
+    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;account_data:Nil;account_seal:Nil;previous_updated_block:0),
+    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;account_data:Nil;account_seal:Nil;previous_updated_block:0),
+    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;account_data:Nil;account_seal:Nil;previous_updated_block:0),
+    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;account_data:Nil;account_seal:Nil;previous_updated_block:0),
+    (account:0;accountInfo:(state:as_Unknown;accountKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil);locked_until_block:0;price:0;account_to_pay:0;new_publicKey:(EC_OpenSSL_NID:0;x:Nil;y:Nil));balance:0;updated_block:0;n_operation:0;name:Nil;account_type:0;account_data:Nil;account_seal:Nil;previous_updated_block:0)
     );
     block_hash:Nil;
     accumulatedWork:0);
@@ -535,7 +539,7 @@ Begin
     If Not TAccountComp.EqualBlockAccounts(bl_my,bl_modified) then begin
       Raise Exception.Create(Format('%s Integrity on modified (i)=%d for block number:%d',[title, i,bl_my.blockchainInfo.block]));
     end;
-    If TBaseType.BinStrComp( sb.CalcBlockHash(bl_modified,sb.FCurrentProtocol>=CT_PROTOCOL_2), bl_modified.block_hash)<>0 then begin
+    If TBaseType.BinStrComp( sb.CalcBlockHash(bl_modified,sb.FCurrentProtocol), bl_modified.block_hash)<>0 then begin
       Raise Exception.Create(Format('%s Integrity on block hash (i)=%d for block number:%d',[title, i,bl_my.blockchainInfo.block]));
     end;
   end;
@@ -1032,10 +1036,12 @@ begin
   end;
 end;
 
-class procedure TAccountComp.SaveAccountToAStream(Stream: TStream; const Account: TAccount);
+class procedure TAccountComp.SaveAccountToAStream(Stream: TStream; const Account: TAccount; current_protocol : Word);
 var w : Word;
 begin
-  w := CT_PROTOCOL_4;
+  if current_protocol<CT_PROTOCOL_5 then
+    w := CT_PROTOCOL_4
+  else w := current_protocol;
   Stream.Write(w,SizeOf(w));
   Stream.Write(Account.account,Sizeof(Account.account));
   TStreamOp.WriteAnsiString(Stream,AccountInfo2RawString(Account.accountInfo));
@@ -1044,17 +1050,21 @@ begin
   Stream.Write(Account.n_operation,Sizeof(Account.n_operation));
   TStreamOp.WriteAnsiString(Stream,Account.name);
   Stream.Write(Account.account_type,SizeOf(Account.account_type));
+  if current_protocol>=CT_PROTOCOL_5 then begin
+    TStreamOp.WriteAnsiString(Stream,Account.account_data);
+    TStreamOp.WriteAnsiString(Stream,Account.account_seal);
+  end;
 end;
 
 class function TAccountComp.LoadAccountFromStream(Stream: TStream; var Account: TAccount): Boolean;
-var w : Word;
+var LSaved_protocol : Word;
   raw : TRawBytes;
 begin
   Account := CT_Account_NUL;
   Result := False;
   if (Stream.Size - Stream.Position<8) then Exit;
-  Stream.Read(w,SizeOf(w));
-  if Not (w in [CT_PROTOCOL_4]) then Exit;
+  Stream.Read(LSaved_protocol,SizeOf(LSaved_protocol));
+  if Not (LSaved_protocol in [CT_PROTOCOL_4,CT_PROTOCOL_5]) then Exit;
   Stream.Read(Account.account,Sizeof(Account.account));
   if TStreamOp.ReadAnsiString(Stream,raw) < 0 then Exit;
   TAccountComp.RawString2AccountInfo(raw,Account.accountInfo);
@@ -1064,6 +1074,10 @@ begin
   Stream.Read(Account.n_operation,Sizeof(Account.n_operation));
   if TStreamOp.ReadAnsiString(Stream,Account.name)<0 then Exit;
   if Stream.Read(Account.account_type,SizeOf(Account.account_type)) <> 2 then Exit;
+  if LSaved_protocol>=CT_PROTOCOL_5 then begin
+    if TStreamOp.ReadAnsiString(Stream,Account.account_data)<0 then Exit;
+    if TStreamOp.ReadAnsiString(Stream,Account.account_seal)<0 then Exit;
+  end;
   Result := True;
 end;
 
@@ -1238,6 +1252,8 @@ begin
           And (account1.n_operation = account2.n_operation)
           And (TBaseType.Equals(account1.name,account2.name))
           And (account1.account_type = account2.account_type)
+          And (TBaseType.Equals(account1.account_data,account2.account_data))
+          And (TBaseType.Equals(account1.account_seal,account2.account_seal))
           And (account1.previous_updated_block = account2.previous_updated_block);
 end;
 
@@ -1365,9 +1381,10 @@ end;
 
 class function TAccountComp.AccountToTxt(const Account: TAccount): String;
 begin
-  Result := Format('%s Balance:%s N_Op:%d UpdB:%d Type:%d Name:%s PK:%s',[AccountNumberToAccountTxtNumber(Account.account),
+  Result := Format('%s Balance:%s N_Op:%d UpdB:%d Type:%d Name:%s PK:%s Data:%s Seal:%s',[AccountNumberToAccountTxtNumber(Account.account),
     FormatMoney(Account.balance),Account.n_operation,Account.updated_block,Account.account_type,
-      Account.name.ToPrintable,TCrypto.ToHexaString(TAccountComp.AccountInfo2RawString(Account.accountInfo))]);
+      Account.name.ToPrintable,TCrypto.ToHexaString(TAccountComp.AccountInfo2RawString(Account.accountInfo)),
+      Account.account_data.ToHexaString,Account.account_seal.ToHexaString ]);
 end;
 
 class function TAccountComp.IsValidAccountInfo(const accountInfo: TAccountInfo; var errors: String): Boolean;
@@ -1567,6 +1584,8 @@ Type
     n_operation: Cardinal;
     name : TRawBytes;
     account_type : Word;
+    account_data : TDynRawBytes;
+    account_seal : T20Bytes;
     previous_updated_block : Cardinal;
   End;
 
@@ -1627,6 +1646,8 @@ begin
   dest.n_operation:=source.n_operation;
   dest.name:=source.name;
   dest.account_type:=source.account_type;
+  dest.account_data:=Copy(source.account_data);
+  dest.account_seal:=TBaseType.To20Bytes(source.account_seal);
   dest.previous_updated_block:=source.previous_updated_block;
   {$ELSE}
   dest := source;
@@ -1656,6 +1677,8 @@ begin
   dest.n_operation:=source.n_operation;
   dest.name:=source.name;
   dest.account_type:=source.account_type;
+  dest.account_data:=Copy(source.account_data);
+  dest.account_seal:=TBaseType.T20BytesToRawBytes(source.account_seal);
   dest.previous_updated_block:=source.previous_updated_block;
   {$ELSE}
   dest := source;
@@ -1848,7 +1871,7 @@ begin
   Inc(FWorkSum,Result.blockchainInfo.compact_target);
   Result.AccumulatedWork := FWorkSum;
   // Calc block hash
-  Result.block_hash := CalcBlockHash(Result,FCurrentProtocol >= CT_PROTOCOL_2);
+  Result.block_hash := CalcBlockHash(Result,FCurrentProtocol);
   If Assigned(FPreviousSafeBox) then begin
     FModifiedBlocksSeparatedChain.Add(Result);
   end else begin
@@ -1984,7 +2007,7 @@ begin
   end;
 end;
 
-class function TPCSafeBox.CalcBlockHash(const block : TBlockAccount; useProtocol2Method : Boolean): TRawBytes;
+class function TPCSafeBox.CalcBlockHash(const block : TBlockAccount; current_protocol : Word): TRawBytes;
   // Protocol v2 update:
   // In order to store values to generate PoW and allow Safebox checkpointing, we
   // store info about TOperationBlock on each row and use it to obtain blockchash
@@ -1994,7 +2017,7 @@ Var raw: TRawBytes;
 begin
   ms := TMemoryStream.Create;
   try
-    If (Not useProtocol2Method) then begin
+    If (Not current_protocol<CT_PROTOCOL_2) then begin
       // PROTOCOL 1 BlockHash calculation
       ms.Write(block.blockchainInfo.block,4); // Little endian
       for i := Low(block.accounts) to High(block.accounts) do begin
@@ -2021,6 +2044,15 @@ begin
           ms.WriteBuffer(block.accounts[i].name[Low(block.accounts[i].name)],Length(block.accounts[i].name));
         end;
         ms.Write(block.accounts[i].account_type,2);
+        if current_protocol>=CT_PROTOCOL_5 then begin
+          // Adding PROTOCOL 5 new fields
+          If Length(block.accounts[i].account_data)>0 then begin
+            ms.WriteBuffer(block.accounts[i].account_data[0],Length(block.accounts[i].account_data));
+          end;
+          If Length(block.accounts[i].account_seal)>0 then begin
+            ms.WriteBuffer(block.accounts[i].account_seal[0],Length(block.accounts[i].account_seal));
+          end;
+        end;
       end;
       ms.Write(block.AccumulatedWork,SizeOf(block.AccumulatedWork));
     end;
@@ -2399,6 +2431,8 @@ procedure TPCSafeBox.CommitToPrevious;
           blockAccount.accounts[j].account_type,
           blockAccount.accounts[j].balance,
           blockAccount.accounts[j].n_operation,
+          blockAccount.accounts[j].account_data,
+          blockAccount.accounts[j].account_seal,
           aus_commiting_from_otherchain,
           blockAccount.accounts[j].updated_block,
           blockAccount.accounts[j].previous_updated_block
@@ -2531,6 +2565,8 @@ procedure TPCSafeBox.RollBackToSnapshot(snapshotBlock: Cardinal);
            blockAccount.accounts[j].account_type,
            blockAccount.accounts[j].balance,
            blockAccount.accounts[j].n_operation,
+           blockAccount.accounts[j].account_data,
+           blockAccount.accounts[j].account_seal,
            aus_rollback,
            blockAccount.accounts[j].updated_block,
            blockAccount.accounts[j].previous_updated_block
@@ -2662,10 +2698,10 @@ begin
   FBufferBlocksHash.Clear;
   for block_number := 0 to BlocksCount - 1 do begin
     {$IFDEF uselowmem}
-    TBaseType.To32Bytes(CalcBlockHash( Block(block_number), True),PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash);
+    TBaseType.To32Bytes(CalcBlockHash( Block(block_number), CT_PROTOCOL_2),PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash);
     FBufferBlocksHash.Add( PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash[0], 32 );
     {$ELSE}
-    PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash := CalcBlockHash( Block(block_number), True);
+    PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash := CalcBlockHash( Block(block_number), CT_PROTOCOL_2);
     FBufferBlocksHash := FBufferBlocksHash+PBlockAccount(FBlockAccountsList.Items[block_number])^.block_hash;
     {$ENDIF}
   end;
@@ -2795,6 +2831,10 @@ begin
             if TStreamOp.ReadAnsiString(Stream,block.accounts[iacc].name)<0 then exit;
             if Stream.Read(block.accounts[iacc].account_type,2)<2 then exit;
           end;
+          if FCurrentProtocol>=CT_PROTOCOL_5 then begin
+            if TStreamOp.ReadAnsiString(Stream,block.accounts[iacc].account_data)<0 then Exit;
+            if TStreamOp.ReadAnsiString(Stream,block.accounts[iacc].account_seal)<0 then Exit;
+          end;
           //
           if Stream.Read(block.accounts[iacc].previous_updated_block,4)<4 then exit;
           // check valid
@@ -2855,7 +2895,7 @@ begin
           end;
 
           // STEP 2: Check if valid block hash
-          if (Not TBaseType.Equals(CalcBlockHash(block,FCurrentProtocol>=CT_PROTOCOL_2),block.block_hash)) then begin
+          if (Not TBaseType.Equals(CalcBlockHash(block,FCurrentProtocol),block.block_hash)) then begin
             errors := errors + ' > Invalid block hash '+inttostr(iblock+1)+'/'+inttostr(sbHeader.blockscount);
             exit;
           end;
@@ -3042,6 +3082,10 @@ begin
         TStreamOp.WriteAnsiString(Stream,b.accounts[iacc].name);
         Stream.Write(b.accounts[iacc].account_type,SizeOf(b.accounts[iacc].account_type));
       end;
+      if FCurrentProtocol>=CT_PROTOCOL_5 then begin
+        TStreamOp.WriteAnsiString(Stream,b.accounts[iacc].account_data);
+        TStreamOp.WriteAnsiString(Stream,b.accounts[iacc].account_seal);
+      end;
       Stream.Write(b.accounts[iacc].previous_updated_block,Sizeof(b.accounts[iacc].previous_updated_block));
     end;
     TStreamOp.WriteAnsiString(Stream,b.block_hash);
@@ -3666,7 +3710,9 @@ begin
   end;
 end;
 
-procedure TPCSafeBox.UpdateAccount(account_number : Cardinal; const newAccountInfo: TAccountInfo; const newName : TRawBytes; newType : Word; newBalance: UInt64; newN_operation: Cardinal;
+procedure TPCSafeBox.UpdateAccount(account_number : Cardinal; const newAccountInfo: TAccountInfo;
+  const newName : TRawBytes; newType : Word; newBalance: UInt64; newN_operation: Cardinal;
+  const newAccountData, newAccountSeal : TRawBytes;
   accountUpdateStyle : TAccountUpdateStyle; newUpdated_block, newPrevious_Updated_block : Cardinal);
 Var iBlock : Cardinal;
   i,j,iAccount, iDeleted, iAdded : Integer;
@@ -3778,8 +3824,12 @@ begin
     end;
   end;
 
+  // New Protocol 5 fields
+  blockAccount.accounts[iAccount].account_data := newAccountData;
+  blockAccount.accounts[iAccount].account_seal := newAccountSeal;
+
   // Save new account values
-  blockAccount.block_hash:=CalcBlockHash(blockAccount,FCurrentProtocol >= CT_PROTOCOL_2);
+  blockAccount.block_hash:=CalcBlockHash(blockAccount,FCurrentProtocol);
   FModifiedBlocksFinalState.Add(blockAccount);
   If Assigned(FPreviousSafeBox) then begin
     FModifiedBlocksSeparatedChain.Add(blockAccount);
@@ -3954,6 +4004,8 @@ begin
             Pa^.account_type,
             Pa^.balance,
             Pa^.n_operation,
+            Pa^.account_data,
+            Pa^.account_seal,
             aus_transaction_commit,
             0,0);
     end;

+ 32 - 0
src/core/UBaseTypes.pas

@@ -48,6 +48,9 @@ Type
   // Fixed 32 bytes length (or empty)
   T32Bytes = Array[0..31] of byte;
 
+  // Fixed 20 bytes length
+  T20Bytes = Array[0..19] of byte;
+
   TRawBytes = TBytes;
 
   { TRawBytesHelper }
@@ -95,6 +98,8 @@ Type
   public
     class procedure T32BytesToRawBytes(const source : T32Bytes; var dest : TDynRawBytes); overload;
     class function T32BytesToRawBytes(const source : T32Bytes) : TDynRawBytes; overload;
+    class procedure T20BytesToRawBytes(const source : T20Bytes; var dest : TDynRawBytes); overload;
+    class function T20BytesToRawBytes(const source : T20Bytes) : TDynRawBytes; overload;
     class function TRawBytesTo32Left0Padded(const source : TDynRawBytes) : T32Bytes;
     class function To256RawBytes(const source : TRawBytes) : T256RawBytes; overload;
     class procedure To256RawBytes(const source : TRawBytes; var dest : T256RawBytes); overload;
@@ -104,6 +109,8 @@ Type
     class procedure ToRawBytes(const source : T32Bytes; var dest: TRawBytes); overload;
     class function To32Bytes(const source : TRawBytes) : T32Bytes; overload;
     class procedure To32Bytes(const source : TRawBytes; var dest: T32Bytes); overload;
+    class function To20Bytes(const source : TRawBytes) : T20Bytes; overload;
+    class procedure To20Bytes(const source : TRawBytes; var dest: T20Bytes); overload;
     class procedure Fill0(var dest : T32Bytes);
     class function IsEmpty(const value : T32Bytes) : Boolean;
     class procedure Concat(const addBytes : T32Bytes; var target : TDynRawBytes); overload;
@@ -236,6 +243,17 @@ begin
   Move(source[0],dest[0],32);
 end;
 
+class function TBaseType.T20BytesToRawBytes(const source: T20Bytes): TDynRawBytes;
+begin
+  T20BytesToRawBytes(source,Result);
+end;
+
+class procedure TBaseType.T20BytesToRawBytes(const source: T20Bytes; var dest: TDynRawBytes);
+begin
+  SetLength(dest,20);
+  Move(source[0],dest[0],20);
+end;
+
 class function TBaseType.T32BytesToRawBytes(const source: T32Bytes): TDynRawBytes;
 begin
   T32BytesToRawBytes(source,Result);
@@ -258,6 +276,20 @@ begin
   move(source[Low(source)],Result[0],Length(source));
 end;
 
+class procedure TBaseType.To20Bytes(const source: TRawBytes; var dest: T20Bytes);
+var i : Integer;
+begin
+  FillByte(dest[0],20,0);
+  i := Length(source);
+  if (i>20) then i:=20;
+  move(source[Low(source)],dest[0],i);
+end;
+
+class function TBaseType.To20Bytes(const source: TRawBytes): T20Bytes;
+begin
+  To20Bytes(source,Result);
+end;
+
 class procedure TBaseType.To256RawBytes(const source: TRawBytes; var dest: T256RawBytes);
 begin
   SetLength(dest,Length(source));

+ 12 - 3
src/core/UNetProtocol.pas

@@ -3341,7 +3341,10 @@ begin
         ocl := sbakl.AccountKeyList[iPubKey];
         while (start<ocl.Count) And (max>0) do begin
           acc := TNode.Node.GetMempoolAccount(ocl.Get(start));
-          TAccountComp.SaveAccountToAStream(accountsStream,acc);
+          if (HeaderData.protocol.protocol_available>9) then
+            TAccountComp.SaveAccountToAStream(accountsStream,acc,CT_PROTOCOL_5)
+          else
+            TAccountComp.SaveAccountToAStream(accountsStream,acc,CT_PROTOCOL_4);
           inc(nAccounts);
           inc(start);
           dec(max);
@@ -3439,7 +3442,10 @@ begin
         responseStream.Write(c,SizeOf(c));
         for i:=start to (start + max -1) do begin
           acc := TNode.Node.GetMempoolAccount(i);
-          TAccountComp.SaveAccountToAStream(responseStream,acc);
+          if (HeaderData.protocol.protocol_available>9) then
+            TAccountComp.SaveAccountToAStream(responseStream,acc,CT_PROTOCOL_5)
+          else
+            TAccountComp.SaveAccountToAStream(responseStream,acc,CT_PROTOCOL_4);
         end;
       end;
     end else if (b=3) then begin
@@ -3451,7 +3457,10 @@ begin
         DataBuffer.Read(c,SizeOf(c));
         if (c>=0) And (c<TNode.Node.Bank.AccountsCount) then begin
           acc := TNode.Node.GetMempoolAccount(c);
-          TAccountComp.SaveAccountToAStream(responseStream,acc);
+          if (HeaderData.protocol.protocol_available>9) then
+            TAccountComp.SaveAccountToAStream(responseStream,acc,CT_PROTOCOL_5)
+          else
+            TAccountComp.SaveAccountToAStream(responseStream,acc,CT_PROTOCOL_4);
         end else begin
           errors := 'Invalid account number '+Inttostr(c);
           Exit;