123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638 |
- unit UDataSources;
- { Copyright (c) 2018 by Herman Schoenfeld
- Distributed under the MIT software license, see the accompanying file LICENSE
- or visit http://www.opensource.org/licenses/mit-license.php.
- This unit is a part of the PascalCoin Project, an infinitely scalable
- cryptocurrency. Find us here:
- Web: https://www.pascalcoin.org
- Source: https://github.com/PascalCoin/PascalCoin
- THIS LICENSE HEADER MUST NOT BE REMOVED.
- }
- {$mode delphi}
- {$modeswitch nestedprocvars}
- interface
- uses
- Classes, SysUtils, UAccounts, UNode, UBlockchain, UCrypto, UCoreObjects,
- UCommon, UMemory, UConst, UCommon.Data, UCoreUtils, UBaseTypes,
- UCommon.Collections, Generics.Collections, Generics.Defaults, syncobjs;
- type
- { TAccountsDataSourceBase }
- TAccountsDataSourceBase = class(TCustomDataSource<TAccount>)
- protected
- function GetColumns: TDataColumns; override;
- public
- function GetItemField(constref AItem: TAccount; const ABindingName: ansistring): variant; override;
- end;
- { TAccountsDataSource }
- TAccountsDataSource = class(TAccountsDataSourceBase)
- protected
- FIncludePending: boolean;
- FKeys: TSortedHashSet<TAccountKey>;
- function GetFilterKeys: TArray<TAccountKey>;
- procedure SetFilterKeys(const AKeys: TArray<TAccountKey>);
- public
- property IncludePending: boolean read FIncludePending write FIncludePending;
- property FilterKeys: TArray<TAccountKey> read GetFilterKeys write SetFilterKeys;
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure FetchAll(const AContainer: TList<TAccount>); override;
- end;
- { TMyAccountsDataSource }
- TMyAccountsDataSource = class(TAccountsDataSource)
- private
- FPBalanceSummary : PBalanceSummary;
- public
- property BalancePointer : PBalanceSummary read FPBalanceSummary write FPBalanceSummary;
- procedure FetchAll(const AContainer: TList<TAccount>); override;
- end;
- { TOperationsDataSourceBase }
- TOperationsDataSourceBase = class(TCustomDataSource<TOperationResume>)
- protected
- function GetColumns: TDataColumns; override;
- public
- function GetItemField(constref AItem: TOperationResume; const ABindingName: ansistring): variant; override;
- end;
- { TAccountsOperationsDataSource }
- TAccountsOperationsDataSource = class(TOperationsDataSourceBase)
- private
- FBlockDepth: Cardinal;
- FAccounts: TArray<cardinal>;
- FLastFetchID : String;
- FLastFetchBlockOperations : TArray<TOperationResume>;
- public
- property Accounts: TArray<cardinal> read FAccounts write FAccounts;
- property BlockDepth: cardinal read FBlockDepth write FBlockDepth;
- procedure FetchAll(const AContainer: TList<TOperationResume>); override;
- end;
- { TPendingOperationsDataSource }
- TPendingOperationsDataSource = class(TOperationsDataSourceBase)
- public
- procedure FetchAll(const AContainer: TList<TOperationResume>); override;
- end;
- { TOperationsDataSource }
- TOperationsDataSource = class(TOperationsDataSourceBase)
- private
- FStartBlock, FEndBlock: Cardinal;
- public
- property StartBlock : Cardinal read FStartBlock write FStartBlock;
- property EndBlock : Cardinal read FEndBlock write FEndBlock;
- procedure FetchAll(const AContainer: TList<TOperationResume>); override;
- end;
- { TBlockSummarySourceBase }
- TBlockSummarySourceBase = class(TCustomDataSource<TBlockSummary>)
- public type
- TShowHashRateAs = (hr_Kilo, hr_Mega, hr_Giga, hr_Tera);
- private
- FStart, FEnd: cardinal;
- FHashRateAs: TShowHashRateAs;
- FHashRateAverageBlocksCount: integer;
- function GetTimeSpan: TTimeSpan;
- procedure SetTimeSpan(const ASpan: TTimeSpan);
- protected
- function GetColumns: TDataColumns; override;
- public
- constructor Create(AOwner: TComponent); override;
- property TimeSpan: TTimeSpan read GetTimeSpan write SetTimeSpan;
- property StartBlock: cardinal read FStart write FStart;
- property EndBlock: cardinal read FEnd write FEnd;
- property HashRateAs: TShowHashRateAs read FHashRateAs write FHashRateAs;
- property HashRateAverageBlocksCount: integer read FHashRateAverageBlocksCount write FHashRateAverageBlocksCount;
- function GetItemField(constref AItem: TBlockSummary; const ABindingName: ansistring): variant; override;
- end;
- { TBlockSummarySource }
- TBlockSummarySource = class(TBlockSummarySourceBase)
- public
- procedure FetchAll(const AContainer: TList<TBlockSummary>); override;
- end;
- implementation
- uses
- Math, UWallet, UTime;
- { TAccountsDataSourceBase }
- function TAccountsDataSourceBase.GetColumns: TDataColumns;
- begin
- Result := TDataColumns.Create(
- TDataColumn.From('AccountNumber', True),
- TDataColumn.From('Account'),
- TDataColumn.From('Name'),
- TDataColumn.From('Display'),
- TDataColumn.From('Balance'),
- TDataColumn.From('BalanceDecimal'),
- TDataColumn.From('Key'),
- TDataColumn.From('Type'),
- TDataColumn.From('State'),
- TDataColumn.From('Price'),
- TDataColumn.From('PriceDecimal'),
- TDataColumn.From('LockedUntil'),
- TDataColumn.From('NOperation'),
- TDataColumn.From('LastUpdatedBlock')
- );
- end;
- function TAccountsDataSourceBase.GetItemField(constref AItem: TAccount; const ABindingName: ansistring): variant;
- var
- index: integer;
- begin
- if ABindingName = 'AccountNumber' then
- Result := AItem.account
- else if ABindingName = 'Account' then
- Result := AItem.AccountString
- else if ABindingName = 'Name' then
- Result := AItem.Name.ToPrintable
- else if ABindingName = 'Display' then
- Result := AItem.DisplayString
- else if ABindingName = 'Balance' then
- Result := AItem.Balance
- else if ABindingName = 'BalanceDecimal' then
- Result := TAccountComp.FormatMoneyDecimal(AItem.Balance)
- else if ABindingName = 'Key' then
- Result := TAccountComp.AccountPublicKeyExport(AItem.accountInfo.accountKey)
- else if ABindingName = 'Type' then
- Result := AItem.account_type
- else if ABindingName = 'State' then
- Result := AItem.accountInfo.state
- else if ABindingName = 'Price' then
- Result := AItem.accountInfo.price
- else if ABindingName = 'PriceDecimal' then
- Result := TAccountComp.FormatMoneyDecimal(AItem.accountInfo.price)
- else if ABindingName = 'LockedUntil' then
- Result := AItem.accountInfo.locked_until_block
- else if ABindingName = 'NOperation' then
- Result := AItem.n_operation
- else if ABindingName = 'LastUpdatedBlock' then
- Result := AItem.updated_block
- else
- raise Exception.Create(Format('Field not found "%s"', [ABindingName]));
- end;
- { TAccountsDataSource }
- constructor TAccountsDataSource.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FKeys := TSortedHashSet<TAccountKey>.Create(TAccountKeyComparer.Create, TAccountKeyEqualityComparer.Create);
- end;
- destructor TAccountsDataSource.Destroy;
- begin
- FKeys.Free;
- end;
- function TAccountsDataSource.GetFilterKeys: TArray<TAccountKey>;
- begin
- EnterLock;
- try
- Result := FKeys.ToArray;
- finally
- ReleaseLock;
- end;
- end;
- procedure TAccountsDataSource.SetFilterKeys(const AKeys: TArray<TAccountKey>);
- var
- i: integer;
- begin
- EnterLock;
- try
- FKeys.Clear;
- for i := Low(AKeys) to High(AKeys) do
- FKeys.Add(AKeys[i]);
- finally
- ReleaseLock;
- end;
- end;
- procedure TAccountsDataSource.FetchAll(const AContainer: TList<TAccount>);
- var
- i: integer;
- acc: TAccount;
- safeBox: TPCSafeBox;
- begin
- safeBox := TNode.Node.Bank.SafeBox;
- safeBox.StartThreadSafe;
- try
- if FKeys.Count = 0 then
- for i := 0 to safeBox.AccountsCount - 1 do
- AContainer.Add(safeBox.Account(i)) // Load all accounts
- else
- for i := 0 to safeBox.AccountsCount - 1 do begin
- // Load key-matching accounts
- if FIncludePending then
- acc := TNode.Node.Operations.SafeBoxTransaction.Account(i)
- else
- acc := safeBox.Account(i);
- if FKeys.Contains(acc.accountInfo.accountKey) then
- AContainer.Add(acc);
- end;
- finally
- safeBox.EndThreadSave;
- end;
- end;
- { TMyAccountsDataSource }
- procedure TMyAccountsDataSource.FetchAll(const AContainer: TList<TAccount>);
- var
- i: integer;
- LAccs: TArray<TAccount>;
- LBalanceSummary : TBalanceSummary;
- begin
- LAccs := TCoreTool.GetUserAccounts(LBalanceSummary, FIncludePending);
- FPBalanceSummary^ := LBalanceSummary;
- if FKeys.Count > 0 then begin
- for i := Low(LAccs) to High(LAccs) do
- if FKeys.Contains(LAccs[i].accountInfo.accountKey) then
- AContainer.Add(LAccs[i]);
- end else AContainer.AddRange(LAccs);
- end;
- { TOperationsDataSourceBase }
- function TOperationsDataSourceBase.GetColumns: TDataColumns;
- begin
- Result := TDataColumns.Create(
- TDataColumn.From('OPHASH', True),
- TDataColumn.From('UnixTime'),
- TDataColumn.From('Time'),
- TDataColumn.From('Block'),
- TDataColumn.From('Index'),
- TDataColumn.From('BlockLocation'),
- TDataColumn.From('BlockLocationSortable'),
- TDataColumn.From('Account'),
- TDataColumn.From('AccountNumber'),
- TDataColumn.From('Type'),
- TDataColumn.From('SubType'),
- TDataColumn.From('Amount'),
- TDataColumn.From('AmountDecimal'),
- TDataColumn.From('Fee'),
- TDataColumn.From('FeeDecimal'),
- TDataColumn.From('Balance'),
- TDataColumn.From('BalanceDecimal'),
- TDataColumn.From('Payload'),
- TDataColumn.From('Description')
- );
- end;
- function TOperationsDataSourceBase.GetItemField(constref AItem: TOperationResume; const ABindingName: ansistring): variant;
- var
- index: integer;
- begin
- if ABindingName = 'OPHASH' then
- Result := TPCOperation.OperationHashAsHexa(AItem.OperationHash)
- else if ABindingName = 'UnixTime' then
- Result := AItem.Time
- else if ABindingName = 'Time' then
- Result := UnixTimeToLocalStr(AItem.time)
- else if ABindingName = 'Block' then
- Result := AItem.Block
- else if ABindingName = 'Index' then
- Result := AItem.NOpInsideBlock
- else if ABindingName = 'BlockLocation' then
- Result := IIF(AItem.OpType <> CT_PseudoOp_Reward, IntToStr(AItem.Block) + '/' + IntToStr(AItem.NOpInsideBlock + 1), IntToStr(AItem.Block))
- else if ABindingName = 'BlockLocationSortable' then
- Result := IIF(AItem.OpType <> CT_PseudoOp_Reward, UInt64(AItem.Block) * 4294967296 + UInt32(AItem.NOpInsideBlock), 0) // number pattern = [block][opindex]
- else if ABindingName = 'Account' then
- Result := TAccountComp.AccountNumberToAccountTxtNumber(AItem.AffectedAccount)
- else if ABindingName = 'AccountNumber' then
- Result := AItem.AffectedAccount
- else if ABindingName = 'Type' then
- Result := AItem.OpType
- else if ABindingName = 'SubType' then
- Result := AItem.OpSubtype
- else if ABindingName = 'Amount' then
- Result := AItem.Amount
- else if ABindingName = 'AmountDecimal' then
- Result := TAccountComp.FormatMoneyDecimal(AItem.Amount)
- else if ABindingName = 'Fee' then
- Result := AItem.Fee
- else if ABindingName = 'FeeDecimal' then
- Result := TAccountComp.FormatMoneyDecimal(AItem.Fee)
- else if ABindingName = 'Balance' then
- Result := AItem.Balance
- else if ABindingName = 'BalanceDecimal' then
- Result := TAccountComp.FormatMoneyDecimal(AItem.Balance)
- else if ABindingName = 'Payload' then
- Result := AItem.PrintablePayload
- else if ABindingName = 'Description' then
- Result := AItem.OperationTxt
- else
- raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
- end;
- { TAccountsOperationsDataSource }
- procedure TAccountsOperationsDataSource.FetchAll(const AContainer: TList<TOperationResume>);
- var
- LNode: TNode;
- LBlockDepth : Integer;
- LFetchID : String;
- LAccounts : TArray<Cardinal>;
- function ComputeFetchID : String;
- var LAccFetchID : string;
- begin
- // note: FAccounts is never empty
- LAccFetchID := Length(FAccounts).ToString + FAccounts[Low(FAccounts)].ToString + FAccounts[High(FAccounts)].ToString;
- Result := LAccFetchID + FBlockDepth.ToString + TCrypto.ToHexaString(LNode.Bank.SafeBox.SafeBoxHash);
- end;
- begin
- if Length(FAccounts) = 0 then
- exit;
- LNode := TNode.Node;
- if not Assigned(LNode) then
- exit;
- LBlockDepth := ClipValue(FBlockDepth, 0, LNode.Bank.BlocksCount);
- LNode.Bank.SafeBox.StartThreadSafe;
- try
- AContainer.AddRange( LNode.GetPendingOperationsAffectingAccounts(FAccounts, 0, MaxInt) );
- // Performance: only fetch from storage if state/args are different from last call
- LFetchID := ComputeFetchID;
- if LFetchID <> FLastFetchID then begin
- FLastFetchID := LFetchID;
- FLastFetchBlockOperations := LNode.GetStoredOperationsAffectingAccounts(FAccounts, LBlockDepth, 0, MaxInt);
- end;
- AContainer.AddRange( FLastFetchBlockOperations );
- finally
- LNode.Bank.SafeBox.EndThreadSave;
- end;
- end;
- { TPendingOperationsDataSource }
- procedure TPendingOperationsDataSource.FetchAll(const AContainer: TList<TOperationResume>);
- var
- i: integer;
- node: TNode;
- Op: TPCOperation;
- OPR: TOperationResume;
- begin
- node := TNode.Node;
- if not Assigned(Node) then
- exit;
- for i := Node.Operations.Count - 1 downto 0 do
- begin
- Op := Node.Operations.OperationsHashTree.GetOperation(i);
- if TPCOperation.OperationToOperationResume(0, Op, False, Op.SignerAccount, OPR) then
- begin
- OPR.NOpInsideBlock := i;
- OPR.Block := Node.Bank.BlocksCount;
- OPR.Balance := Node.Operations.SafeBoxTransaction.Account(Op.SignerAccount).balance;
- AContainer.Add(OPR);
- end;
- end;
- end;
- { TOperationsDataSource }
- procedure TOperationsDataSource.FetchAll(const AContainer: TList<TOperationResume>);
- var
- block, i, j, keyIndex: integer;
- OPR: TOperationResume;
- blockOps: TPCOperationsComp;
- node: TNode;
- GC: TDisposables;
- begin
- node := TNode.Node;
- if not Assigned(Node) then
- exit;
- blockOps := GC.AddObject(TPCOperationsComp.Create(nil)) as TPCOperationsComp;
- for block := FEndBlock downto FStartBlock do
- begin /// iterate blocks correctly
- opr := CT_TOperationResume_NUL;
- if (Node.Bank.Storage.LoadBlockChainBlock(blockOps, block)) then begin
- AContainer.Add(blockOps.GetMinerRewardPseudoOperation);
- // if blockOps.Count = 0 then exit;
- for i := blockOps.Count - 1 downto 0 do
- if TPCOperation.OperationToOperationResume(block, blockOps.Operation[i], False, blockOps.Operation[i].SignerAccount, opr) then begin
- opr.NOpInsideBlock := i;
- opr.Block := block;
- opr.time := blockOps.OperationBlock.timestamp;
- AContainer.Add(opr);
- end; // reverse order
- end else break;
- end;
- end;
- { TBlockSummarySourceBase }
- function TBlockSummarySourceBase.GetTimeSpan: TTimeSpan;
- begin
- Result := TTimeSpan.FromSeconds(CT_NewLineSecondsAvg * (FEnd - FStart + 1));
- end;
- procedure TBlockSummarySourceBase.SetTimeSpan(const ASpan: TTimeSpan);
- var
- LNode: TNode;
- begin
- LNode := TNode.Node;
- if not Assigned(LNode) then
- exit;
- FEnd := LNode.Bank.BlocksCount - 1;
- FStart := ClipValue(FEnd - (ASpan.TotalBlockCount + 1), 0, FEnd);
- end;
- function TBlockSummarySourceBase.GetColumns: TDataColumns;
- var
- LHashType: string;
- begin
- case HashRateAs of
- hr_Kilo: LHashType := 'Kh/s';
- hr_Mega: LHashType := 'Mh/s';
- hr_Giga: LHashType := 'Gh/s';
- hr_Tera: LHashType := 'Th/s';
- else LHashType := '?h/s';
- end;
- Result := TDataColumns.Create(
- TDataColumn.From('UnixTime'),
- TDataColumn.From('Time'),
- TDataColumn.From('Block'),
- TDataColumn.From('Ops'),
- TDataColumn.From(LHashType),
- TDataColumn.From('Volume'),
- TDataColumn.From('Reward'),
- TDataColumn.From('Fee'),
- TDataColumn.From('FeeDecimal'),
- TDataColumn.From('Target'),
- TDataColumn.From('MinerPayload'),
- TDataColumn.From('POW'),
- TDataColumn.From('SBH'),
- TDataColumn.From('Protocol'),
- TDataColumn.From('Deviation'),
- TDataColumn.From('TimeAverage')
- );
- end;
- constructor TBlockSummarySourceBase.Create(AOwner: TComponent);
- var
- LNode: TNode;
- begin
- inherited Create(AOwner);
- LNode := TNode.Node;
- if Assigned(LNode) then begin
- FStart := 0;
- FEnd := LNode.Bank.BlocksCount - 1;
- end else begin
- FStart := 0;
- FEnd := 0;
- end;
- end;
- function TBlockSummarySourceBase.GetItemField(constref AItem: TBlockSummary; const ABindingName: ansistring): variant;
- var
- LHR_Base: int64;
- LHashType: string;
- LDeviation: double;
- begin
- case FHashRateAs of
- hr_Kilo: LHashType := 'Kh/s';
- hr_Mega: LHashType := 'Mh/s';
- hr_Giga: LHashType := 'Gh/s';
- hr_Tera: LHashType := 'Th/s';
- else LHashType := '?h/s';
- end;
- //if ABindingName = 'UnixTime' then
- // Result := DateTimeToStr(UnivDateTime2LocalDateTime(UnixToUnivDateTime((AItem.Timestamp))))
- //else if ABindingName = 'Time' then
- // Result := DateTimeToStr(UnivDateTime2LocalDateTime(UnixToUnivDateTime((AItem.Timestamp))))
- if ABindingName = 'UnixTime' then
- Result := AItem.Timestamp
- else if ABindingName = 'Time' then
- Result := UnixTimeToLocalStr(AItem.Timestamp)
- else if ABindingName = 'Block' then
- Result := AItem.Block
- else if ABindingName = 'Ops' then
- Result := AItem.OperationsCount
- else if ABindingName = 'Volume' then
- Result := TAccountComp.FormatMoney(AItem.Volume)
- else if ABindingName = 'Reward' then
- Result := TAccountComp.FormatMoney(AItem.Reward)
- else if ABindingName = 'Fee' then
- Result := AItem.Fee
- else if ABindingName = 'FeeDecimal' then
- Result := TAccountComp.FormatMoneyDecimal(AItem.Fee)
- else if ABindingName = 'Target' then
- Result := IntToHex(AItem.Target, 8)
- else if ABindingName = LHashType then begin
- case HashRateAs of
- hr_Kilo: LHR_Base := 1;
- hr_Mega: LHR_Base := 1000;
- hr_Giga: LHR_Base := 1000000;
- hr_Tera: LHR_Base := 1000000000;
- else
- Result := 1;
- end;
- Result := Format('%.2n (%.2n)', [AItem.HashRateKhs / LHR_Base, AItem.HashRateTargetKhs / LHR_Base]);
- end else if ABindingName = 'MinerPayload' then begin
- if TCrypto.IsHumanReadable(AItem.MinerPayload) then
- Result := AItem.MinerPayload
- else
- Result := TCrypto.ToHexaString(AItem.MinerPayload);
- end else if ABindingName = 'POW' then
- Result := TCrypto.ToHexaString(AItem.PoW)
- else if ABindingName = 'SBH' then
- Result := TCrypto.ToHexaString(AItem.SafeBoxHash)
- else if ABindingName = 'Protocol' then
- Result := IntToStr(AItem.BlockProtocolVersion) + '-' + IntToStr(AItem.BlockProtocolAvailable)
- else if ABindingName = 'Deviation' then begin
- LDeviation := ((CT_NewLineSecondsAvg - AItem.TimeAverage100) / CT_NewLineSecondsAvg) * 100;
- Result := Format('%.2f', [LDeviation]) + ' %';
- end else if ABindingName = 'TimeAverage' then
- Result := Format('200:%.1f 150:%.1f 100:%.1f 75:%.1f 50:%.1f 25:%.1f 10:%.1f', [AItem.TimeAverage200, AItem.TimeAverage150, AItem.TimeAverage100, AItem.TimeAverage75, AItem.TimeAverage50, AItem.TimeAverage25, AItem.TimeAverage10])
- else
- raise Exception.Create(Format('Field not found [%s]', [ABindingName]));
- end;
- { TBlockSummarySource }
- procedure TBlockSummarySource.FetchAll(const AContainer: TList<TBlockSummary>);
- var
- LStart, LEnd, LIdx: cardinal;
- LOperationComp: TPCOperationsComp;
- LBlockChainData: TBlockSummary;
- LOperationBlock: TOperationBlock;
- LBigNum: TBigNum;
- LNode: TNode;
- begin
- LNode := TNode.Node;
- if not Assigned(LNode) then
- Exit;
- if LNode.Bank.BlocksCount <= 0 then
- Exit;
- LEnd := EndBlock;
- LStart := StartBlock;
- LOperationComp := TPCOperationsComp.Create(nil);
- try
- LOperationComp.bank := LNode.Bank;
- for LIdx := LEnd downto LStart do begin
- LBlockChainData := CT_BlockSummary_NUL;
- LOperationBlock := LNode.Bank.SafeBox.Block(LIdx).blockchainInfo;
- LBlockChainData.Block := LOperationBlock.block;
- LBlockChainData.Timestamp := LOperationBlock.timestamp;
- LBlockChainData.BlockProtocolVersion := LOperationBlock.protocol_version;
- LBlockChainData.BlockProtocolAvailable := LOperationBlock.protocol_available;
- LBlockChainData.Reward := LOperationBlock.reward;
- LBlockChainData.Fee := LOperationBlock.fee;
- LBlockChainData.Target := LOperationBlock.compact_target;
- LBlockChainData.HashRateKhs := LNode.Bank.SafeBox.CalcBlockHashRateInKhs(LBlockChainData.Block, HashRateAverageBlocksCount);
- LBigNum := TBigNum.TargetToHashRate(LOperationBlock.compact_target);
- try
- LBlockChainData.HashRateTargetKhs := LBigNum.Divide(1024).Divide(CT_NewLineSecondsAvg).Value;
- finally
- LBigNum.Free;
- end;
- LBlockChainData.MinerPayload := LOperationBlock.block_payload;
- LBlockChainData.PoW := LOperationBlock.proof_of_work;
- LBlockChainData.SafeBoxHash := LOperationBlock.initial_safe_box_hash;
- LBlockChainData.AccumulatedWork := LNode.Bank.SafeBox.Block(LBlockChainData.Block).AccumulatedWork;
- if (LNode.Bank.LoadOperations(LOperationComp, LIdx)) then begin
- LBlockChainData.OperationsCount := LOperationComp.Count;
- LBlockChainData.Volume := LOperationComp.OperationsHashTree.TotalAmount + LOperationComp.OperationsHashTree.TotalFee;
- end;
- LBlockChainData.TimeAverage200 := LNode.Bank.GetTargetSecondsAverage(LBlockChainData.Block, 200);
- LBlockChainData.TimeAverage150 := LNode.Bank.GetTargetSecondsAverage(LBlockChainData.Block, 150);
- LBlockChainData.TimeAverage100 := LNode.Bank.GetTargetSecondsAverage(LBlockChainData.Block, 100);
- LBlockChainData.TimeAverage75 := LNode.Bank.GetTargetSecondsAverage(LBlockChainData.Block, 75);
- LBlockChainData.TimeAverage50 := LNode.Bank.GetTargetSecondsAverage(LBlockChainData.Block, 50);
- LBlockChainData.TimeAverage25 := LNode.Bank.GetTargetSecondsAverage(LBlockChainData.Block, 25);
- LBlockChainData.TimeAverage10 := LNode.Bank.GetTargetSecondsAverage(LBlockChainData.Block, 10);
- AContainer.Add(LBlockChainData);
- end;
- finally
- LOperationComp.Free;
- end;
- end;
- end.
|