Browse Source

AnsiString to String -> core

Also correcting duplicates on TAccountComp.AccountKeyFromImport
PascalCoin 6 years ago
parent
commit
7dba4480a3
2 changed files with 58 additions and 98 deletions
  1. 53 95
      src/core/UAccounts.pas
  2. 5 3
      src/core/UNetProtocol.pas

+ 53 - 95
src/core/UAccounts.pas

@@ -837,7 +837,6 @@ Var
   bn, bn2: TBigNum;
   i: Int64;
   nbits, min_compact_target: Cardinal;
-  c: AnsiChar;
   raw : TRawBytes;
   j : Integer;
 begin
@@ -969,7 +968,7 @@ begin
 end;
 
 { TAccountComp }
-Const CT_Base58 : AnsiString = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
+Const CT_Base58 : String = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
 
 class function TAccountComp.AccountBlock(const account_number: Cardinal): Cardinal;
 begin
@@ -1065,58 +1064,8 @@ begin
 end;
 
 class function TAccountComp.AccountKeyFromImport(const HumanReadable: String; var account: TAccountKey; var errors : String): Boolean;
-Var raw : TRawBytes;
-  BN, BNAux, BNBase : TBigNum;
-  i,j : Integer;
-  s1,s2 : RawByteString;
-  i64 : Int64;
-  b : Byte;
 begin
-  result := false;
-  errors := 'Invalid length';
-  account := CT_TECDSA_Public_Nul;
-  if length(HumanReadable)<20 then exit;
-  BN := TBigNum.Create(0);
-  BNAux := TBigNum.Create;
-  BNBase := TBigNum.Create(1);
-  try
-    for i := length(HumanReadable) downto 1 do begin
-      if (HumanReadable[i]<>' ') then begin
-        j := pos(HumanReadable[i],CT_Base58);
-        if j=0 then begin
-          errors := 'Invalid char "'+HumanReadable[i]+'" at pos '+inttostr(i)+'/'+inttostr(length(HumanReadable));
-          exit;
-        end;
-        BNAux.Value := j-1;
-        BNAux.Multiply(BNBase);
-        BN.Add(BNAux);
-        BNBase.Multiply(length(CT_Base58));
-      end;
-    end;
-    // Last 8 hexa chars are the checksum of others
-    s1 := Copy(BN.HexaValue,3,length(BN.HexaValue));
-    s2 := copy(s1,length(s1)-7,8);
-    s1 := copy(s1,1,length(s1)-8);
-    raw := TCrypto.HexaToRaw(s1);
-    s1 := TCrypto.ToHexaString( TCrypto.DoSha256(raw) );
-    if copy(s1,1,8)<>s2 then begin
-      // Invalid checksum
-      errors := 'Invalid checksum';
-      exit;
-    end;
-    try
-      account := TAccountComp.RawString2Accountkey(raw);
-      Result := true;
-      errors := '';
-    except
-      // Nothing to do... invalid
-      errors := 'Error on conversion from Raw to Account key';
-    end;
-  Finally
-    BN.Free;
-    BNBase.Free;
-    BNAux.Free;
-  end;
+  Result := AccountPublicKeyImport(HumanReadable,account,errors);
 end;
 
 class function TAccountComp.AccountNumberToAccountTxtNumber(account_number: Cardinal): String;
@@ -1141,7 +1090,7 @@ begin
     BN.HexaValue := '01'+raw.ToHexaString+TCrypto.ToHexaString(Copy(TCrypto.DoSha256(raw),0,4));
     while (Not BN.IsZero) do begin
       BN.Divide(BNDiv,BNMod);
-      If (BNMod.Value>=0) And (BNMod.Value<length(CT_Base58)) then Result := CT_Base58[Byte(BNMod.Value)+Low(String)] + Result
+      If (BNMod.Value>=0) And (BNMod.Value<Length(CT_Base58)) then Result := CT_Base58.Chars[Byte(BNMod.Value)] + Result
       else raise Exception.Create('Error converting to Base 58');
     end;
   finally
@@ -1151,53 +1100,58 @@ begin
   end;
 end;
 
-class function TAccountComp.AccountPublicKeyImport(
-  const HumanReadable: String; var account: TAccountKey;
-  var errors: String): Boolean;
-Var raw : TRawBytes;
+class function TAccountComp.AccountPublicKeyImport(const HumanReadable: String; var account: TAccountKey; var errors: String): Boolean;
+Var raw,rawPubKey,rawChecksum_Calculated,rawChecksum_Stored : TRawBytes;
   BN, BNAux, BNBase : TBigNum;
   i,j : Integer;
-  s1,s2 : String;
-  i64 : Int64;
-  b : Byte;
 begin
-  result := false;
-  errors := 'Invalid length';
+  Result := false;
   account := CT_TECDSA_Public_Nul;
-  if length(HumanReadable)<20 then exit;
+  if Length(HumanReadable)<20 then begin
+    errors := 'Invalid length';
+    Exit(False);
+  end;
   BN := TBigNum.Create(0);
   BNAux := TBigNum.Create;
   BNBase := TBigNum.Create(1);
   try
-    for i := length(HumanReadable) downto 1 do begin
-      j := pos(HumanReadable[i],CT_Base58);
-      if j=0 then begin
-        errors := 'Invalid char "'+HumanReadable[i]+'" at pos '+inttostr(i)+'/'+inttostr(length(HumanReadable));
-        exit;
+    for i := Length(HumanReadable)-1 downto 0 do begin
+      j := CT_Base58.IndexOf(HumanReadable.Chars[i]);
+      if j<0 then begin
+        errors := 'Invalid char "'+HumanReadable.Chars[i]+'" at pos '+inttostr(i+1)+'/'+inttostr(Length(HumanReadable));
+        Exit(False);
       end;
-      BNAux.Value := j-1;
+      BNAux.Value := j;
       BNAux.Multiply(BNBase);
       BN.Add(BNAux);
-      BNBase.Multiply(length(CT_Base58));
+      BNBase.Multiply(Length(CT_Base58));
     end;
     // Last 8 hexa chars are the checksum of others
-    s1 := Copy(BN.HexaValue,3,length(BN.HexaValue));
-    s2 := copy(s1,length(s1)-7,8);
-    s1 := copy(s1,1,length(s1)-8);
-    raw := TCrypto.HexaToRaw(s1);
-    s1 := TCrypto.ToHexaString( TCrypto.DoSha256(raw) );
-    if copy(s1,1,8)<>s2 then begin
+    raw := TCrypto.HexaToRaw(BN.HexaValue);
+    if (Length(raw)<5) then begin
+      errors := 'Invalid decoded';
+      Exit(False);
+    end;
+    if (raw[0]<>1) then begin
+      errors := 'Invalid start value';
+      Exit(False);
+    end;
+    rawPubKey := Copy(raw,1,Length(raw)-5);
+    rawChecksum_Stored := Copy(raw,Length(raw)-4,4);
+    rawChecksum_Calculated := Copy(TCrypto.DoSha256(rawPubKey),0,4);
+    if (Not TBaseType.Equals(rawChecksum_Calculated,rawChecksum_Stored)) then begin
       // Invalid checksum
       errors := 'Invalid checksum';
-      exit;
+      Exit(False);
     end;
     try
-      account := TAccountComp.RawString2Accountkey(raw);
-      Result := true;
+      account := TAccountComp.RawString2Accountkey(rawPubKey);
       errors := '';
+      Result := True;
     except
       // Nothing to do... invalid
       errors := 'Error on conversion from Raw to Account key';
+      Result := False;
     end;
   Finally
     BN.Free;
@@ -1207,31 +1161,35 @@ begin
 end;
 
 class function TAccountComp.AccountTxtNumberToAccountNumber(const account_txt_number: String; var account_number: Cardinal): Boolean;
+  // PascalCoin account number can be a simple number "123456" or a number with checksum separated by "-","." or "_"
+  // The CHECKSUM is 2 digits between 10..88 (89 posibilities)
+  // Calculation of checksum: Account number multiplied by 101, moduled by 89 and adding 10
+  // Example:
+  //   "1234" : Good, no checksum
+  //   "1234-5" : Invalid. Correct checksum is 44  (((1234 * 101) MODULUS 89)+10)=44
+  //   "1234-44" : Good, checksum for 1234 is 44
+  //   "1234 44" : Invalid. Separator is not "-","." or "_"
 Var i : Integer;
-  char1 : AnsiChar;
-  char2 : AnsiChar;
   an,rn,anaux : Int64;
 begin
-  Result := false;
-  if length(trim(account_txt_number))=0 then exit;
+  if Length(Trim(account_txt_number))=0 then Exit(False);
   an := 0;
-  i := 1;
-  while (i<=length(account_txt_number)) do begin
-    if account_txt_number[i] in ['0'..'9'] then begin
-      an := (an * 10) + ord( account_txt_number[i] ) - ord('0');
+  i := 0;
+  while (i<Length(account_txt_number)) do begin
+    if account_txt_number.Chars[i] in ['0'..'9'] then begin
+      an := (an * 10) + ord( account_txt_number.Chars[i] ) - ord('0');
     end else begin
-      break;
+      Break;
     end;
     inc(i);
   end;
   account_number := an;
-  if (i>length(account_txt_number)) then begin
-    result := true;
-    exit;
+  if (i>=Length(account_txt_number)) then begin
+    Exit(True);
   end;
-  if (account_txt_number[i] in ['-','.',' ']) then inc(i);
-  if length(account_txt_number)-1<>i then exit;
-  rn := StrToIntDef(copy(account_txt_number,i,length(account_txt_number)),0);
+  if (account_txt_number.Chars[i] in ['-','.','_']) then inc(i);
+  if i>=Length(account_txt_number) then Exit(False);  // Found invalid chars after account number
+  rn := StrToIntDef(account_txt_number.Substring(i,Length(account_txt_number)),0);
   anaux := ((an * 101) MOD 89)+10;
   Result := rn = anaux;
 end;

+ 5 - 3
src/core/UNetProtocol.pas

@@ -2583,6 +2583,7 @@ end;
 procedure TNetConnection.DisconnectInvalidClient(ItsMyself : Boolean; const why: String);
 Var include_in_list : Boolean;
   ns : TNodeServerAddress;
+  aux_s : String;
 begin
   FIsDownloadingBlocks := false;
   if ItsMyself then begin
@@ -2591,9 +2592,10 @@ begin
     TLog.NewLog(lterror,Classname,'Disconecting '+ClientRemoteAddr+' > '+Why);
   end;
   FIsMyselfServer := ItsMyself;
-  include_in_list := (Not SameText(Client.RemoteHost,'localhost')) And (Not SameText('127.',Client.RemoteHost.Substring(0,4)))
-    And (Not SameText('192.168.',Client.RemoteHost.Substring(0,8)))
-    And (Not SameText('10.',Client.RemoteHost.Substring(0,3)));
+  aux_s := Client.RemoteHost;
+  include_in_list := (Not SameText(aux_s,'localhost')) And (Not SameText('127.',aux_s.Substring(0,4)))
+    And (Not SameText('192.168.',aux_s.Substring(0,8)))
+    And (Not SameText('10.',aux_s.Substring(0,3)));
   if include_in_list then begin
     If TNetData.NetData.NodeServersAddresses.GetNodeServerAddress(Client.RemoteHost,Client.RemotePort,true,ns) then begin
       ns.last_connection := UnivDateTimeToUnix(DateTime2UnivDateTime(now));