Skip to content
This repository has been archived by the owner on Dec 7, 2023. It is now read-only.

Added blockchain show block/transactions/contracts commands #905

Merged
merged 22 commits into from
Nov 27, 2023
Merged
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 225 additions & 0 deletions neo-cli/CLI/MainService.Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
// modifications are permitted.

using Neo.ConsoleService;
using Neo.Json;
using Neo.Network.P2P.Payloads;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Org.BouncyCastle.Asn1.Cms;
using System;
using System.Linq;
using System.Security.Policy;

namespace Neo.CLI
{
Expand Down Expand Up @@ -41,5 +47,224 @@ private void OnExportBlocksStartCountCommand(uint start, uint count = uint.MaxVa

WriteBlocks(start, count, path, true);
}

[ConsoleCommand("show block", Category = "Blockchain Commands")]
private void OnPrintBlockCommand(string indexOrHash)
{
Block block = null;

if (uint.TryParse(indexOrHash, out var index))
block = NativeContract.Ledger.GetBlock(_neoSystem.StoreView, index);
else if (UInt256.TryParse(indexOrHash, out var hash))
block = NativeContract.Ledger.GetBlock(_neoSystem.StoreView, hash);
else
{
ConsoleHelper.Error("Enter a valid block index or hash.");
return;
}

if (block == null)
{
ConsoleHelper.Error($"Block {indexOrHash} doesn't exist.");
return;
}

DateTime blockDatetime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
blockDatetime = blockDatetime.AddMilliseconds(block.Timestamp).ToLocalTime();

ConsoleHelper.Info("", "-------------", "Block", "-------------");
ConsoleHelper.Info();
ConsoleHelper.Info("", " Timestamp: ", $"{blockDatetime}");
ConsoleHelper.Info("", " Index: ", $"{block.Index}");
ConsoleHelper.Info("", " Hash: ", $"{block.Hash}");
ConsoleHelper.Info("", " Nonce: ", $"{block.Nonce}");
ConsoleHelper.Info("", " MerkleRoot: ", $"{block.MerkleRoot}");
ConsoleHelper.Info("", " PrevHash: ", $"{block.PrevHash}");
ConsoleHelper.Info("", " NextConsensus: ", $"{block.NextConsensus}");
ConsoleHelper.Info("", " PrimaryIndex: ", $"{block.PrimaryIndex}");
ConsoleHelper.Info("", " Version: ", $"{block.Version}");
ConsoleHelper.Info("", " Size: ", $"{block.Size} Byte(s)");
ConsoleHelper.Info();
ConsoleHelper.Info("", "-------------", "Witness", "-------------");
ConsoleHelper.Info();
ConsoleHelper.Info("", " Invocation Script: ", $"{Convert.ToBase64String(block.Witness.InvocationScript.Span)}");
ConsoleHelper.Info("", " Verification Script: ", $"{Convert.ToBase64String(block.Witness.VerificationScript.Span)}");
ConsoleHelper.Info("", " ScriptHash: ", $"{block.Witness.ScriptHash}");
ConsoleHelper.Info("", " Size: ", $"{block.Witness.Size} Byte(s)");
ConsoleHelper.Info();
ConsoleHelper.Info("", "-------------", "Transactions", "-------------");
ConsoleHelper.Info();

cschuchardt88 marked this conversation as resolved.
Show resolved Hide resolved
if (block.Transactions.Length == 0)
ConsoleHelper.Info("", " No Transaction(s)");

foreach (var tx in block.Transactions)
ConsoleHelper.Info($" {tx.Hash}");
ConsoleHelper.Info();
ConsoleHelper.Info("", "--------------------------------------");

}

[ConsoleCommand("show tx", Category = "Blockchain Commands")]
public void OnPrintTransactionCommand(UInt256 hash)
{
var tx = NativeContract.Ledger.GetTransactionState(_neoSystem.StoreView, hash);

if (tx == null)
{
ConsoleHelper.Error($"Transaction {hash} doesn't exist.");
return;
}

var block = NativeContract.Ledger.GetHeader(_neoSystem.StoreView, tx.BlockIndex);

DateTime transactionDatetime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
transactionDatetime = transactionDatetime.AddMilliseconds(block.Timestamp).ToLocalTime();

ConsoleHelper.Info("", "-------------", "Transaction", "-------------");
ConsoleHelper.Info();
ConsoleHelper.Info("", " Timestamp: ", $"{transactionDatetime}");
ConsoleHelper.Info("", " Hash: ", $"{tx.Transaction.Hash}");
ConsoleHelper.Info("", " Nonce: ", $"{tx.Transaction.Nonce}");
ConsoleHelper.Info("", " Sender: ", $"{tx.Transaction.Sender}");
ConsoleHelper.Info("", " ValidUntilBlock: ", $"{tx.Transaction.ValidUntilBlock}");
ConsoleHelper.Info("", " FeePerByte: ", $"{tx.Transaction.FeePerByte}");
ConsoleHelper.Info("", " NetworkFee: ", $"{tx.Transaction.NetworkFee}");
ConsoleHelper.Info("", " SystemFee: ", $"{tx.Transaction.SystemFee}");
ConsoleHelper.Info("", " Script: ", $"{Convert.ToBase64String(tx.Transaction.Script.Span)}");
ConsoleHelper.Info("", " Version: ", $"{tx.Transaction.Version}");
ConsoleHelper.Info("", " BlockIndex: ", $"{block.Index}");
ConsoleHelper.Info("", " BlockHash: ", $"{block.Hash}");
ConsoleHelper.Info("", " Size: ", $"{tx.Transaction.Size} Byte(s)");
ConsoleHelper.Info();
ConsoleHelper.Info("", "-------------", "Signers", "-------------");
ConsoleHelper.Info();
foreach (var signer in tx.Transaction.Signers)
{
if (signer.Rules.Length == 0)
ConsoleHelper.Info("", " Rules: ", "[]");
else
ConsoleHelper.Info("", " Rules: ", $"[{string.Join(", ", signer.Rules.Select(s => $"\"{s.ToJson()}\""))}]");
ConsoleHelper.Info("", " Account: ", $"{signer.Account}");
ConsoleHelper.Info("", " Scopes: ", $"{signer.Scopes}");
if (signer.AllowedContracts.Length == 0)
ConsoleHelper.Info("", " AllowedContracts: ", "[]");
else
ConsoleHelper.Info("", " AllowedContracts: ", $"[{string.Join(", ", signer.AllowedContracts.Select(s => s.ToString()))}]");
if (signer.AllowedGroups.Length == 0)
ConsoleHelper.Info("", " AllowedGroups: ", "[]");
else
ConsoleHelper.Info("", " AllowedGroups: ", $"[{string.Join(", ", signer.AllowedGroups.Select(s => s.ToString()))}]");
ConsoleHelper.Info("", " Size: ", $"{signer.Size} Byte(s)");
ConsoleHelper.Info();
}
ConsoleHelper.Info("", "-------------", "Witnesses", "-------------");
ConsoleHelper.Info();
foreach (var witness in tx.Transaction.Witnesses)
{
ConsoleHelper.Info("", " InvocationScript: ", $"{Convert.ToBase64String(witness.InvocationScript.Span)}");
ConsoleHelper.Info("", " VerificationScript: ", $"{Convert.ToBase64String(witness.VerificationScript.Span)}");
ConsoleHelper.Info("", " ScriptHash: ", $"{witness.ScriptHash}");
ConsoleHelper.Info("", " Size: ", $"{witness.Size} Byte(s)");
ConsoleHelper.Info();
}
ConsoleHelper.Info("", "-------------", "Attributes", "-------------");
ConsoleHelper.Info();
if (tx.Transaction.Attributes.Length == 0)
{
ConsoleHelper.Info("", " No Attribute(s).");
ConsoleHelper.Info();
}
foreach (var attribute in tx.Transaction.Attributes)
{
ConsoleHelper.Info("", " Type: ", $"{attribute.Type}");
ConsoleHelper.Info("", " AllowMultiple: ", $"{attribute.AllowMultiple}");
ConsoleHelper.Info("", " Size: ", $"{attribute.Size} Byte(s)");
ConsoleHelper.Info();
}
ConsoleHelper.Info("", "--------------------------------------");
}

[ConsoleCommand("show contract", Category = "Blockchain Commands")]
public void OnPrintContractCommand(string nameOrHash)
{
ContractState contract = null;

if (UInt160.TryParse(nameOrHash, out var scriptHash))
contract = NativeContract.ContractManagement.GetContract(_neoSystem.StoreView, scriptHash);
else
{
var nativeContract = NativeContract.Contracts.SingleOrDefault(s => s.Name.Equals(nameOrHash, StringComparison.InvariantCultureIgnoreCase));

if (nativeContract != null)
contract = NativeContract.ContractManagement.GetContract(_neoSystem.StoreView, nativeContract.Hash);
}

if (contract == null)
{
ConsoleHelper.Error($"Contract {nameOrHash} doesn't exist.");
return;
}

ConsoleHelper.Info("", "-------------", "Contract", "-------------");
ConsoleHelper.Info();
ConsoleHelper.Info("", " Name: ", $"{contract.Manifest.Name}");
ConsoleHelper.Info("", " Hash: ", $"{contract.Hash}");
ConsoleHelper.Info("", " Id: ", $"{contract.Id}");
ConsoleHelper.Info("", " UpdateCounter: ", $"{contract.UpdateCounter}");
ConsoleHelper.Info("", " SupportedStandards: ", $"{string.Join(" ", contract.Manifest.SupportedStandards)}");
ConsoleHelper.Info("", " Checksum: ", $"{contract.Nef.CheckSum}");
ConsoleHelper.Info("", " Compiler: ", $"{contract.Nef.Compiler}");
ConsoleHelper.Info("", " SourceCode: ", $"{contract.Nef.Source}");
ConsoleHelper.Info("", " Trusts: ", $"[{string.Join(", ", contract.Manifest.Trusts.Select(s => s.ToJson()?.GetString()))}]");
if (contract.Manifest.Extra != null)
{
foreach (var extra in contract.Manifest.Extra.Properties)
{
ConsoleHelper.Info("", $" {extra.Key,18}: ", $"{extra.Value?.GetString()}");
}
}
ConsoleHelper.Info();
ConsoleHelper.Info("", "-------------", "Groups", "-------------");
ConsoleHelper.Info();
if (contract.Manifest.Groups.Length == 0)
{
ConsoleHelper.Info("", " No Group(s).");
ConsoleHelper.Info();
}
foreach (var group in contract.Manifest.Groups)
{
ConsoleHelper.Info("", " PubKey: ", $"{group.PubKey}");
ConsoleHelper.Info("", " Signature: ", $"{Convert.ToBase64String(group.Signature)}");
ConsoleHelper.Info();
}
ConsoleHelper.Info("", "-------------", "Permissions", "-------------");
ConsoleHelper.Info();
foreach (var permission in contract.Manifest.Permissions)
{
ConsoleHelper.Info("", " Contract: ", $"{permission.Contract.ToJson()?.GetString()}");
if (permission.Methods.IsWildcard)
ConsoleHelper.Info("", " Methods: ", "*");
else
ConsoleHelper.Info("", " Methods: ", $"{string.Join(", ", permission.Methods)}");
ConsoleHelper.Info();
}
ConsoleHelper.Info("", "-------------", "Methods", "-------------");
ConsoleHelper.Info();
foreach (var method in contract.Manifest.Abi.Methods)
{
ConsoleHelper.Info("", " Name: ", $"{method.Name}");
ConsoleHelper.Info("", " Safe: ", $"{method.Safe}");
ConsoleHelper.Info("", " Offset: ", $"{method.Offset}");
ConsoleHelper.Info("", " Parameters: ", $"[{string.Join(", ", method.Parameters.Select(s => s.Type.ToString()))}]");
ConsoleHelper.Info("", " ReturnType: ", $"{method.ReturnType}");
ConsoleHelper.Info();
}
ConsoleHelper.Info("", "-------------", "Script", "-------------");
ConsoleHelper.Info();
ConsoleHelper.Info($" {Convert.ToBase64String(contract.Nef.Script.Span)}");
ConsoleHelper.Info();
ConsoleHelper.Info("", "--------------------------------");
}
}
}