From 235a4c224d6695f0640a06de58f706f849bbd8e6 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Wed, 28 Dec 2022 23:32:07 +0600 Subject: [PATCH 01/20] added hardfork15 --- src/Lachain.Core/Blockchain/Hardfork/HardforkConfig.cs | 1 + .../Blockchain/Hardfork/HardforkHeights.cs | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/Lachain.Core/Blockchain/Hardfork/HardforkConfig.cs b/src/Lachain.Core/Blockchain/Hardfork/HardforkConfig.cs index 6df367843..a8fcd8fdb 100644 --- a/src/Lachain.Core/Blockchain/Hardfork/HardforkConfig.cs +++ b/src/Lachain.Core/Blockchain/Hardfork/HardforkConfig.cs @@ -18,5 +18,6 @@ public class HardforkConfig [JsonProperty("hardfork_12")] public ulong? Hardfork_12 { get; set; } [JsonProperty("hardfork_13")] public ulong? Hardfork_13 { get; set; } [JsonProperty("hardfork_14")] public ulong? Hardfork_14 { get; set; } + [JsonProperty("hardfork_15")] public ulong? Hardfork_15 { get; set; } } } \ No newline at end of file diff --git a/src/Lachain.Core/Blockchain/Hardfork/HardforkHeights.cs b/src/Lachain.Core/Blockchain/Hardfork/HardforkHeights.cs index ed408acd4..dca921ab8 100644 --- a/src/Lachain.Core/Blockchain/Hardfork/HardforkHeights.cs +++ b/src/Lachain.Core/Blockchain/Hardfork/HardforkHeights.cs @@ -19,6 +19,7 @@ public static class HardforkHeights private static ulong Hardfork_12; private static ulong Hardfork_13; private static ulong Hardfork_14; + private static ulong Hardfork_15; //we need this value as default deploy height public static ulong GetHardfork_3() @@ -96,6 +97,11 @@ public static bool IsHardfork_14Active(ulong height) { return height >= Hardfork_14; } + + public static bool IsHardfork_15Active(ulong height) + { + return height >= Hardfork_15; + } public static void SetHardforkHeights(HardforkConfig hardforkConfig) { @@ -159,6 +165,10 @@ public static void SetHardforkHeights(HardforkConfig hardforkConfig) if(hardforkConfig.Hardfork_14 is null) throw new Exception("hardfork_14 is null"); Hardfork_14 = (ulong) hardforkConfig.Hardfork_14; + + if(hardforkConfig.Hardfork_15 is null) + throw new Exception("hardfork_15 is null"); + Hardfork_15 = (ulong) hardforkConfig.Hardfork_15; } } } From 20c6b7aecd0ad1e92ec055e330f6050c470142f0 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Wed, 28 Dec 2022 23:32:24 +0600 Subject: [PATCH 02/20] updated config for hardfork --- src/Lachain.Core/Config/ConfigManager.cs | 34 +++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Lachain.Core/Config/ConfigManager.cs b/src/Lachain.Core/Config/ConfigManager.cs index 35a261946..cf9b225d2 100644 --- a/src/Lachain.Core/Config/ConfigManager.cs +++ b/src/Lachain.Core/Config/ConfigManager.cs @@ -14,7 +14,7 @@ namespace Lachain.Core.Config { public class ConfigManager : IConfigManager { - private const ulong _CurrentVersion = 17; + private const ulong _CurrentVersion = 18; private IDictionary _config; public string ConfigPath { get; } public RunOptions CommandLineOptions { get; } @@ -88,6 +88,12 @@ private void _UpdateConfigVersion() _UpdateConfigToV16(); if (version < 17) _UpdateConfigToV17(); + if (version < 18) + _UpdateConfigToV18(); + version = GetConfig("versionInfo")?.Version ?? + throw new ApplicationException("No version section in config"); + if (version != _CurrentVersion) + throw new ApplicationException("Version not updated properly"); } // version 2 of config should contain hardfork section and height for first hardfork, @@ -515,6 +521,32 @@ private void _UpdateConfigToV17() _SaveCurrentConfig(); } + + // version 18 of config should contain hardfork_15 + private void _UpdateConfigToV18() + { + var network = GetConfig("network") ?? + throw new ApplicationException("No network section in config"); + + var hardforks = GetConfig("hardfork") ?? + throw new ApplicationException("No hardfork section in config"); + hardforks.Hardfork_15 ??= network.NetworkName switch + { + "mainnet" => 6212300, + "testnet" => 5928300, + "devnet" => 1651300, + _ => 0 + }; + _config["hardfork"] = JObject.FromObject(hardforks); + + var version = GetConfig("version") ?? + throw new ApplicationException("No version section in config"); + + version.Version = 18; + _config["version"] = JObject.FromObject(version); + + _SaveCurrentConfig(); + } private void _SaveCurrentConfig() { From f657a9fc3c93abe7ba925b3148463e7ae0aa3e4d Mon Sep 17 00:00:00 2001 From: tbssajal Date: Wed, 28 Dec 2022 23:33:08 +0600 Subject: [PATCH 03/20] removed add and sub balance method, added verification in transfer method, provide mint method for minting token --- src/Lachain.Storage/State/BalanceSnapshot.cs | 55 ++++++++++++++++--- src/Lachain.Storage/State/IBalanceSnapshot.cs | 7 +-- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/Lachain.Storage/State/BalanceSnapshot.cs b/src/Lachain.Storage/State/BalanceSnapshot.cs index 9f9f526b0..fb3969ba2 100644 --- a/src/Lachain.Storage/State/BalanceSnapshot.cs +++ b/src/Lachain.Storage/State/BalanceSnapshot.cs @@ -1,11 +1,13 @@ -using System.Runtime.CompilerServices; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; using Lachain.Crypto; +using Lachain.Logger; using Lachain.Proto; +using Lachain.Storage.DbCompact; +using Lachain.Storage.Trie; using Lachain.Utility; using Lachain.Utility.Utils; -using Lachain.Storage.Trie; -using System.Collections.Generic; -using Lachain.Storage.DbCompact; namespace Lachain.Storage.State { @@ -15,6 +17,7 @@ Balance Snapshot is basically a HMAT (trie) and it stores the balance of all the */ public class BalanceSnapshot : IBalanceSnapshot { + private static readonly ILogger Logger = LoggerFactory.GetLoggerForClass(); private readonly IStorageState _state; private static readonly ICrypto Crypto = CryptoProvider.GetCrypto(); @@ -61,21 +64,21 @@ public Money GetSupply() } [MethodImpl(MethodImplOptions.Synchronized)] - public void SetBalance(UInt160 owner, Money value) + private void SetBalance(UInt160 owner, Money value) { var key = EntryPrefix.BalanceByOwnerAndAsset.BuildPrefix(owner); _state.AddOrUpdate(key, value.ToUInt256().ToBytes()); } [MethodImpl(MethodImplOptions.Synchronized)] - public void SetSupply(Money value) + private void SetSupply(Money value) { var key = EntryPrefix.TotalSupply.BuildPrefix(); _state.AddOrUpdate(key, value.ToUInt256().ToBytes()); } [MethodImpl(MethodImplOptions.Synchronized)] - public Money AddBalance(UInt160 owner, Money value, bool increaseSupply = false) + private Money AddBalance(UInt160 owner, Money value, bool increaseSupply = false) { var balance = GetBalance(owner); balance += value; @@ -91,7 +94,7 @@ public Money AddBalance(UInt160 owner, Money value, bool increaseSupply = false) } [MethodImpl(MethodImplOptions.Synchronized)] - public Money SubBalance(UInt160 owner, Money value) + private Money SubBalance(UInt160 owner, Money value) { var balance = GetBalance(owner); balance -= value; @@ -100,15 +103,49 @@ public Money SubBalance(UInt160 owner, Money value) } [MethodImpl(MethodImplOptions.Synchronized)] - public bool TransferBalance(UInt160 from, UInt160 to, Money value) + public bool TransferBalance( + UInt160 from, UInt160 to, Money value, TransactionReceipt receipt, bool checkSignature, bool useNewChainId + ) { var availableBalance = GetBalance(from); if (availableBalance.CompareTo(value) < 0) return false; + if (checkSignature) + { + if (UInt160Utils.IsZero(from)) + { + if (!UInt160Utils.IsZero(receipt.Transaction.From)) + { + return false; + } + } + else + { + try + { + var owner = receipt.RecoverPublicKey(useNewChainId).GetAddress(); + if (!owner.Equals(from)) + { + return false; + } + } + catch (Exception exc) + { + Logger.LogWarning($"Could not recover public key for receipt {receipt.Hash.ToHex()}: {exc}"); + return false; + } + } + } SubBalance(from, value); AddBalance(to, value); return true; } + + [MethodImpl(MethodImplOptions.Synchronized)] + public Money MintLaToken(UInt160 address, Money value) + { + return AddBalance(address, value, true); + } [MethodImpl(MethodImplOptions.Synchronized)] public Money GetAllowedSupply() diff --git a/src/Lachain.Storage/State/IBalanceSnapshot.cs b/src/Lachain.Storage/State/IBalanceSnapshot.cs index e2bd18482..862ce76c8 100644 --- a/src/Lachain.Storage/State/IBalanceSnapshot.cs +++ b/src/Lachain.Storage/State/IBalanceSnapshot.cs @@ -7,17 +7,14 @@ public interface IBalanceSnapshot : ISnapshot { Money GetBalance(UInt160 owner); Money GetSupply(); - void SetBalance(UInt160 owner, Money value); - Money AddBalance(UInt160 owner, Money value, bool increaseSupply = false); - Money SubBalance(UInt160 owner, Money value); - - bool TransferBalance(UInt160 from, UInt160 to, Money value); + bool TransferBalance(UInt160 from, UInt160 to, Money value, TransactionReceipt receipt, bool checkSignature, bool useNewChainId); Money GetAllowedSupply(); void SetAllowedSupply(Money value); UInt160 GetMinter(); void SetMinter(UInt160 minter); + Money MintLaToken(UInt160 address, Money value); } } \ No newline at end of file From 4e56aeb7fc72a647c31d39a42cc9d01f02f9f683 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Wed, 28 Dec 2022 23:33:31 +0600 Subject: [PATCH 04/20] updated tx executer --- .../Blockchain/Operations/TransactionExecuter.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Lachain.Core/Blockchain/Operations/TransactionExecuter.cs b/src/Lachain.Core/Blockchain/Operations/TransactionExecuter.cs index 3600e2c90..173680e8b 100644 --- a/src/Lachain.Core/Blockchain/Operations/TransactionExecuter.cs +++ b/src/Lachain.Core/Blockchain/Operations/TransactionExecuter.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Lachain.Core.Blockchain.Error; +using Lachain.Core.Blockchain.Hardfork; using Lachain.Core.Blockchain.Interface; using Lachain.Core.Blockchain.SystemContracts.ContractManager; using Lachain.Core.Blockchain.VM; @@ -56,7 +57,7 @@ public OperatingError Execute(Block block, TransactionReceipt receipt, IBlockcha { if (!receipt.Transaction.From.Equals(UInt160Utils.Zero)) return OperatingError.InvalidTransaction; if (!receipt.Transaction.Invocation.IsEmpty) return OperatingError.InvalidTransaction; - snapshot.Balances.AddBalance(receipt.Transaction.To, transaction.Value.ToMoney(), true); + snapshot.Balances.MintLaToken(receipt.Transaction.To, transaction.Value.ToMoney()); return OperatingError.Ok; } @@ -85,7 +86,10 @@ public OperatingError Execute(Block block, TransactionReceipt receipt, IBlockcha /* try to transfer funds from sender to recipient */ if (new Money(transaction.Value) > Money.Zero) - if (!snapshot.Balances.TransferBalance(transaction.From, transaction.To, new Money(transaction.Value))) + if (!snapshot.Balances.TransferBalance( + transaction.From, transaction.To, new Money(transaction.Value), receipt, + HardforkHeights.IsHardfork_15Active(receipt.Block), HardforkHeights.IsHardfork_9Active(receipt.Block) + )) return OperatingError.InsufficientBalance; /* invoke required function or fallback */ return _InvokeContract( From 932c304bf5386bb207dcdc161196228f1d605f80 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Thu, 29 Dec 2022 22:30:39 +0600 Subject: [PATCH 05/20] methods for contract balance transfer --- src/Lachain.Storage/State/BalanceSnapshot.cs | 67 ++++++++++++++----- src/Lachain.Storage/State/IBalanceSnapshot.cs | 20 ++++++ 2 files changed, 71 insertions(+), 16 deletions(-) diff --git a/src/Lachain.Storage/State/BalanceSnapshot.cs b/src/Lachain.Storage/State/BalanceSnapshot.cs index fb3969ba2..da1c34502 100644 --- a/src/Lachain.Storage/State/BalanceSnapshot.cs +++ b/src/Lachain.Storage/State/BalanceSnapshot.cs @@ -112,28 +112,18 @@ public bool TransferBalance( return false; if (checkSignature) { - if (UInt160Utils.IsZero(from)) + try { - if (!UInt160Utils.IsZero(receipt.Transaction.From)) + var owner = receipt.RecoverPublicKey(useNewChainId).GetAddress(); + if (!owner.Equals(from)) { return false; } } - else + catch (Exception exc) { - try - { - var owner = receipt.RecoverPublicKey(useNewChainId).GetAddress(); - if (!owner.Equals(from)) - { - return false; - } - } - catch (Exception exc) - { - Logger.LogWarning($"Could not recover public key for receipt {receipt.Hash.ToHex()}: {exc}"); - return false; - } + Logger.LogWarning($"Could not recover public key for receipt {receipt.Hash.ToHex()}: {exc}"); + return false; } } SubBalance(from, value); @@ -183,6 +173,51 @@ public void SetMinter(UInt160 value) _state.AddOrUpdate(key, value.ToBytes()); } + [MethodImpl(MethodImplOptions.Synchronized)] + public Money RemoveCollectedFees(Money fee, TransactionReceipt receipt) + { + if (!receipt.Transaction.From.Equals(UInt160Utils.Zero)) + throw new Exception($"Non system contract transaction {receipt.Hash.ToHex()} requests RemoveCollectedFees"); + return SubBalance(SystemContractAddresses.GovernanceContract, fee); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public bool TransferContractBalance(UInt160 from, UInt160 to, Money value) + { + var availableBalance = GetBalance(from); + if (availableBalance.CompareTo(value) < 0) + return false; + SubBalance(from, value); + AddBalance(to, value); + return true; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public bool TransferSystemContractBalance( + UInt160 from, UInt160 to, Money value, TransactionReceipt receipt, bool checkVerification + ) + { + if (checkVerification) + { + if (!SystemContractAddresses.IsSystemContract(from)) + return false; + // for balance transfer of system contract, either the transaction is a system contract transaion + // or the sender sent a transaction to a system contract (like withdraw stake) and that contract did this transfer + // external contract should not request system contract balance transfer + if (!receipt.Transaction.From.Equals(UInt160Utils.Zero) + && !SystemContractAddresses.IsSystemContract(receipt.Transaction.To)) + { + return false; + } + } + var availableBalance = GetBalance(from); + if (availableBalance.CompareTo(value) < 0) + return false; + SubBalance(from, value); + AddBalance(to, value); + return true; + } + public void Commit(RocksDbAtomicWrite batch) { _state.Commit(batch); diff --git a/src/Lachain.Storage/State/IBalanceSnapshot.cs b/src/Lachain.Storage/State/IBalanceSnapshot.cs index 862ce76c8..69bf58403 100644 --- a/src/Lachain.Storage/State/IBalanceSnapshot.cs +++ b/src/Lachain.Storage/State/IBalanceSnapshot.cs @@ -14,7 +14,27 @@ public interface IBalanceSnapshot : ISnapshot void SetAllowedSupply(Money value); UInt160 GetMinter(); void SetMinter(UInt160 minter); + /// + /// Mints LaToken by increasing balance of address. + /// Total supply is also increased. + /// Should not be called unless token is supposed to be minted. + /// + /// updated balance of address Money MintLaToken(UInt160 address, Money value); + Money RemoveCollectedFees(Money fee, TransactionReceipt receipt); + /// + /// Transfers balance from a contract to an address. + /// Plain address balance transfer should not call this method + /// + /// true if transferred successfully, false otherwise + bool TransferContractBalance(UInt160 from, UInt160 to, Money value); + /// + /// Transfers balance from a system contract to an address. + /// Plain address balance transfer should not call this method. + /// This methods should only be used in System contracts + /// + /// true if transferred successfully, false otherwise + bool TransferSystemContractBalance(UInt160 from, UInt160 to, Money value, TransactionReceipt receipt, bool checkVerification); } } \ No newline at end of file From a16f54690d4b813b0df0356b17d087d3d7a8c4ef Mon Sep 17 00:00:00 2001 From: tbssajal Date: Thu, 29 Dec 2022 22:32:01 +0600 Subject: [PATCH 06/20] using correct methods for balance transfer --- src/Lachain.Benchmark/BlockchainBenchmark.cs | 24 ++-- .../Blockchain/Operations/BlockManager.cs | 8 +- .../SystemContracts/GovernanceContract.cs | 8 +- .../SystemContracts/NativeTokenContract.cs | 117 ++++++++++++++++-- .../SystemContracts/StakingContract.cs | 4 +- .../Blockchain/VM/ExternalHandler.cs | 70 +++++++++-- .../Blockchain/VM/InvocationContext.cs | 2 +- 7 files changed, 194 insertions(+), 39 deletions(-) diff --git a/src/Lachain.Benchmark/BlockchainBenchmark.cs b/src/Lachain.Benchmark/BlockchainBenchmark.cs index 7cdbfd956..b1cb33e31 100644 --- a/src/Lachain.Benchmark/BlockchainBenchmark.cs +++ b/src/Lachain.Benchmark/BlockchainBenchmark.cs @@ -295,8 +295,10 @@ private void _Bench_Emulate_Block( const int txPerBlock = 1000; Logger.LogInformation($"Setting initial balance for the 'From' address"); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(keyPair.PublicKey.GetAddress(), - Money.Parse("200000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken( + keyPair.PublicKey.GetAddress(), + Money.Parse("200000") + ); var txReceipts = new List(); @@ -352,8 +354,10 @@ private void _Bench_Emulate_Execute_Tx( const int txPerBlock = 1000; Logger.LogInformation($"Setting initial balance for the 'From' address"); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(keyPair.PublicKey.GetAddress(), - Money.Parse("200000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken( + keyPair.PublicKey.GetAddress(), + Money.Parse("200000") + ); var txReceipts = new List(); @@ -414,8 +418,10 @@ private void _Bench_Tx_Pool( const int txPerBlock = 1000; Logger.LogInformation($"Setting initial balance for the 'From' address"); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(keyPair.PublicKey.GetAddress(), - Money.Parse("200000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken( + keyPair.PublicKey.GetAddress(), + Money.Parse("200000") + ); var txReceipts = new List(); for (int i = 0; i < txGenerate; i++) @@ -463,8 +469,10 @@ private void _Bench_Execute_Blocks( const int txPerBlock = 10; Logger.LogInformation($"Setting initial balance for the 'From' address"); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(keyPair.PublicKey.GetAddress(), - Money.Parse("2000000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken( + keyPair.PublicKey.GetAddress(), + Money.Parse("2000000") + ); for (var k = 0; k < txGenerate / txPerBlock; k++) { diff --git a/src/Lachain.Core/Blockchain/Operations/BlockManager.cs b/src/Lachain.Core/Blockchain/Operations/BlockManager.cs index dd4fc0bf9..456742437 100644 --- a/src/Lachain.Core/Blockchain/Operations/BlockManager.cs +++ b/src/Lachain.Core/Blockchain/Operations/BlockManager.cs @@ -622,8 +622,10 @@ private OperatingError _TakeTransactionFee( return OperatingError.InsufficientBalance; } - return !snapshot.Balances.TransferBalance(transaction.Transaction.From, - ContractRegisterer.GovernanceContract, fee) + return !snapshot.Balances.TransferBalance( + transaction.Transaction.From, ContractRegisterer.GovernanceContract, fee, transaction, + HardforkHeights.IsHardfork_15Active(transaction.Block), HardforkHeights.IsHardfork_9Active(transaction.Block) + ) ? OperatingError.InsufficientBalance : OperatingError.Ok; } @@ -839,7 +841,7 @@ public bool TryBuildGenesisBlock() // add balance to staking contract var stakeAmount = Money.Parse(validator.StakeAmount); - snapshot.Balances.AddBalance(ContractRegisterer.StakingContract, stakeAmount, true); + snapshot.Balances.MintLaToken(ContractRegisterer.StakingContract, stakeAmount); // set stake value _userToStake.SetValue(validatorAddress, stakeAmount.ToUInt256().ToBytes()); // update stakers list diff --git a/src/Lachain.Core/Blockchain/SystemContracts/GovernanceContract.cs b/src/Lachain.Core/Blockchain/SystemContracts/GovernanceContract.cs index a424a9f69..ae3c26ad4 100644 --- a/src/Lachain.Core/Blockchain/SystemContracts/GovernanceContract.cs +++ b/src/Lachain.Core/Blockchain/SystemContracts/GovernanceContract.cs @@ -159,14 +159,12 @@ public ExecutionStatus DistributeCycleRewardsAndPenalties(UInt256 cycle, SystemC if (txFeesAmount > Money.Zero) { - _context.Snapshot.Balances.SubBalance( - ContractRegisterer.GovernanceContract, txFeesAmount - ); + _context.Snapshot.Balances.RemoveCollectedFees(txFeesAmount, _context.Receipt); } var totalReward = GetBlockReward().ToMoney() * (int) StakingContract.CycleDuration + txFeesAmount; - _context.Sender = ContractRegisterer.GovernanceContract; - var staking = new StakingContract(_context); + var nextContext = _context.NextContext(ContractRegisterer.GovernanceContract); + var staking = new StakingContract(nextContext); staking.DistributeRewardsAndPenalties(totalReward.ToUInt256(), frame); Emit(GovernanceInterface.EventDistributeCycleRewardsAndPenalties, totalReward.ToUInt256()); return ExecutionStatus.Ok; diff --git a/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs b/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs index 0e8749b9d..2d548af06 100644 --- a/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs +++ b/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs @@ -120,11 +120,50 @@ public ExecutionStatus Transfer(UInt160 recipient, UInt256 value, SystemContract { frame.UseGas(GasMetering.NativeTokenTransferCost); var from = _context.Sender ?? throw new InvalidOperationException(); - var result = _context.Snapshot.Balances.TransferBalance( - from, - recipient, - value.ToMoney() - ); + bool result; + if (HardforkHeights.IsHardfork_15Active(_context.Receipt.Block)) + { + var contract = _context.Snapshot.Contracts.GetContractByHash(from); + var isSystemContract = SystemContractAddresses.IsSystemContract(from); + if ((contract is null) && !isSystemContract) + { + // balance transfer from plain address + result = _context.Snapshot.Balances.TransferBalance( + from, + recipient, + value.ToMoney(), + _context.Receipt, + HardforkHeights.IsHardfork_15Active(_context.Receipt.Block), + HardforkHeights.IsHardfork_9Active(_context.Receipt.Block) + ); + } + else if (isSystemContract) + { + // balance transfer from system contract address + // system contract balance transfer can happen here because the sender is the sender of the current context + // which means it is not possible to overwrite the sender address or pass via input data of transaction + result = _context.Snapshot.Balances.TransferSystemContractBalance( + from, recipient, value.ToMoney(), _context.Receipt, + HardforkHeights.IsHardfork_15Active(_context.Receipt.Block) + ); + } + else + { + // balance transfer from contract address + result = _context.Snapshot.Balances.TransferContractBalance(from, recipient, value.ToMoney()); + } + } + else + { + result = _context.Snapshot.Balances.TransferBalance( + from, + recipient, + value.ToMoney(), + _context.Receipt, + HardforkHeights.IsHardfork_15Active(_context.Receipt.Block), + HardforkHeights.IsHardfork_9Active(_context.Receipt.Block) + ); + } Emit(Lrc20Interface.EventTransfer, from, recipient, value); frame.ReturnValue = ContractEncoder.Encode(null, (result ? 1 : 0).ToUInt256()); if (HardforkHeights.IsHardfork_13Active(frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight())) @@ -140,7 +179,71 @@ public ExecutionStatus TransferFrom( frame.UseGas(GasMetering.NativeTokenTransferFromCost); if (!SubAllowance(from, Sender(), value, frame)) return ExecutionStatus.ExecutionHalted; - var result = _context.Snapshot.Balances.TransferBalance(from, recipient, value.ToMoney()); + bool result; + if (HardforkHeights.IsHardfork_15Active(_context.Receipt.Block)) + { + var contract = _context.Snapshot.Contracts.GetContractByHash(from); + var isSystemContract = SystemContractAddresses.IsSystemContract(from); + if ((contract is null) && !isSystemContract) + { + // balance transfer from plain address + result = _context.Snapshot.Balances.TransferBalance( + from, + recipient, + value.ToMoney(), + _context.Receipt, + HardforkHeights.IsHardfork_15Active(_context.Receipt.Block), + HardforkHeights.IsHardfork_9Active(_context.Receipt.Block) + ); + } + else if (isSystemContract) + { + // balance transfer from system contract address + // for system contract balance transfer, the sender of this invocation has to be a system contract + var sender = _context.Sender; + isSystemContract = SystemContractAddresses.IsSystemContract(sender); + if (isSystemContract) + { + result = _context.Snapshot.Balances.TransferSystemContractBalance( + from, recipient, value.ToMoney(), _context.Receipt, + HardforkHeights.IsHardfork_15Active(_context.Receipt.Block) + ); + } + else + { + // will not transfer balance of system contract + result = false; + } + + } + else + { + // balance transfer from contract address + // for this case the sender of the current invocation has to be a contract address + // and should be equal to from address + var sender = _context.Sender; + if (!(sender is null) && sender.Equals(from)) + { + result = _context.Snapshot.Balances.TransferContractBalance(from, recipient, value.ToMoney()); + } + else + { + // will not transfer balance of contract + result = false; + } + } + } + else + { + result = _context.Snapshot.Balances.TransferBalance( + from, + recipient, + value.ToMoney(), + _context.Receipt, + HardforkHeights.IsHardfork_15Active(_context.Receipt.Block), + HardforkHeights.IsHardfork_9Active(_context.Receipt.Block) + ); + } Emit(Lrc20Interface.EventTransfer, from, recipient, value); frame.ReturnValue = ContractEncoder.Encode(null, (result ? 1 : 0).ToUInt256()); if (HardforkHeights.IsHardfork_13Active(frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight())) @@ -200,7 +303,7 @@ public ExecutionStatus Mint(UInt160 address, UInt256 amount, SystemContractExecu totalSupply + amountMoney > _context.Snapshot.Balances.GetAllowedSupply()) return ExecutionStatus.ExecutionHalted; - var newBalance = _context.Snapshot?.Balances.AddBalance(address, amountMoney, true); + var newBalance = _context.Snapshot?.Balances.MintLaToken(address, amountMoney); if (newBalance is null) return ExecutionStatus.ExecutionHalted; Emit(Lrc20Interface.EventMinted, address, amount); diff --git a/src/Lachain.Core/Blockchain/SystemContracts/StakingContract.cs b/src/Lachain.Core/Blockchain/SystemContracts/StakingContract.cs index 97d15723e..094ab97df 100644 --- a/src/Lachain.Core/Blockchain/SystemContracts/StakingContract.cs +++ b/src/Lachain.Core/Blockchain/SystemContracts/StakingContract.cs @@ -704,8 +704,8 @@ public ExecutionStatus DistributeRewardsAndPenalties(UInt256 totalReward, System var rewardToMint = SubPenalty(validatorAddress, validatorReward); if (rewardToMint > Money.Zero) { - var newBalance = _context.Snapshot.Balances.AddBalance( - validatorAddress, rewardToMint, true + var newBalance = _context.Snapshot.Balances.MintLaToken( + validatorAddress, rewardToMint ); Logger.LogDebug($"Minted reward: {rewardToMint} LA for {validatorAddress.ToHex()}"); Logger.LogDebug($"New balance: {newBalance} LA of {validatorAddress.ToHex()}"); diff --git a/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs b/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs index f5c4f359a..7bb71a022 100644 --- a/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs +++ b/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Google.Protobuf; using Lachain.Core.Blockchain.Error; +using Lachain.Core.Blockchain.Hardfork; using Lachain.Core.Blockchain.SystemContracts.ContractManager; using Lachain.Core.Blockchain.SystemContracts.Interface; using Lachain.Core.Blockchain.SystemContracts.Utils; @@ -12,11 +13,11 @@ using Lachain.Crypto; using Lachain.Logger; using Lachain.Proto; +using Lachain.Storage.State; using Lachain.Utility; using Lachain.Utility.Serialization; using Lachain.Utility.Utils; using WebAssembly.Runtime; -using Lachain.Core.Blockchain.Hardfork; using Nethereum.ABI.Util; namespace Lachain.Core.Blockchain.VM @@ -169,11 +170,12 @@ private static int InvokeContract( } frame.UseGas(GasMetering.TransferFundsGasCost); - var result = snapshot.Balances.TransferBalance(GetHardfork_5CurrentAddressOrDelegate(frame), address, value); + var transferFrom = GetHardfork_5CurrentAddressOrDelegate(frame); + var result = TransferBalance(transferFrom, address, value, frame); if (!result) throw new InsufficientFundsException(); - Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, GetHardfork_5CurrentAddressOrDelegate(frame), address, value); + Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, transferFrom, address, value); } if (snapshot.Contracts.GetContractByHash(address) is null) { @@ -370,10 +372,11 @@ public static int Handler_Env_Transfer( if (value > Money.Zero) { frame.UseGas(GasMetering.TransferFundsGasCost); - var result = snapshot.Balances.TransferBalance(GetHardfork_5CurrentAddressOrDelegate(frame), address, value); + var transferFrom = GetHardfork_5CurrentAddressOrDelegate(frame); + var result = TransferBalance(transferFrom, address, value, frame); if (!result) throw new InsufficientFundsException(); - Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, GetHardfork_5CurrentAddressOrDelegate(frame), address, value); + Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, transferFrom, address, value); } return 0; @@ -460,8 +463,9 @@ private static int Handler_Env_Create_V1(int valueOffset, int dataOffset, int da // transfer funds frame.UseGas(GasMetering.TransferFundsGasCost); - snapshot.Balances.TransferBalance(GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); - Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); + var transferFrom = GetHardfork_5CurrentAddressOrDelegate(frame); + TransferBalance(transferFrom, hash, value, frame); + Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, transferFrom, hash, value); SafeCopyToMemory(frame.Memory, hash.ToBytes(), resultOffset); @@ -566,8 +570,9 @@ private static int Handler_Env_Create_V2(int valueOffset, int dataOffset, int da // transfer funds frame.UseGas(GasMetering.TransferFundsGasCost); - snapshot.Balances.TransferBalance(GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); - Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); + var transferFrom = GetHardfork_5CurrentAddressOrDelegate(frame); + TransferBalance(transferFrom, hash, value, frame); + Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, transferFrom, hash, value); SafeCopyToMemory(frame.Memory, hash.ToBytes(), resultOffset); @@ -655,8 +660,9 @@ public static int Handler_Env_Create2_V1(int valueOffset, int dataOffset, int da // transfer funds frame.UseGas(GasMetering.TransferFundsGasCost); - snapshot.Balances.TransferBalance(GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); - Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); + var transferFrom = GetHardfork_5CurrentAddressOrDelegate(frame); + TransferBalance(transferFrom, hash, value, frame); + Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, transferFrom, hash, value); SafeCopyToMemory(frame.Memory, hash.ToBytes(), resultOffset); @@ -760,8 +766,9 @@ public static int Handler_Env_Create2_V2(int valueOffset, int dataOffset, int da // transfer funds frame.UseGas(GasMetering.TransferFundsGasCost); - snapshot.Balances.TransferBalance(GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); - Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, GetHardfork_5CurrentAddressOrDelegate(frame), hash, value); + var transferFrom = GetHardfork_5CurrentAddressOrDelegate(frame); + TransferBalance(transferFrom, hash, value, frame); + Emit(frame.InvocationContext, Lrc20Interface.EventTransfer, transferFrom, hash, value); SafeCopyToMemory(frame.Memory, hash.ToBytes(), resultOffset); @@ -1473,6 +1480,43 @@ public static void Handler_Env_GetChainId(int dataOffset) throw new InvalidContractException("Bad call to (get_chain_id)"); } + private static bool TransferBalance( + UInt160 from, UInt160 to, Money value, IExecutionFrame frame + ) + { + var receipt = frame.InvocationContext.Receipt; + var snapshot = frame.InvocationContext.Snapshot; + var height = snapshot.Blocks.GetTotalBlockHeight(); + if (HardforkHeights.IsHardfork_15Active(height)) + { + var contract = snapshot.Contracts.GetContractByHash(from); + if (contract is null) + { + // balance transfer from plain address + return snapshot.Balances.TransferBalance( + from, to, value, receipt, + HardforkHeights.IsHardfork_15Active(height), HardforkHeights.IsHardfork_9Active(height) + ); + } + else + { + // balance transfer from contract address + // the sender of the current invocation should be equal to from + var sender = frame.InvocationContext.Sender; + if (!(sender is null) && sender.Equals(from)) + return snapshot.Balances.TransferContractBalance(from, to, value); + else return false; + } + } + else + { + return snapshot.Balances.TransferBalance( + from, to, value, receipt, + HardforkHeights.IsHardfork_15Active(height), HardforkHeights.IsHardfork_9Active(height) + ); + } + } + private static FunctionImport CreateImport(string methodName) { var methodInfo = typeof(ExternalHandler).GetMethod(methodName) ?? throw new ArgumentNullException(); diff --git a/src/Lachain.Core/Blockchain/VM/InvocationContext.cs b/src/Lachain.Core/Blockchain/VM/InvocationContext.cs index 30c6c35ed..74bd5b86f 100644 --- a/src/Lachain.Core/Blockchain/VM/InvocationContext.cs +++ b/src/Lachain.Core/Blockchain/VM/InvocationContext.cs @@ -8,7 +8,7 @@ namespace Lachain.Core.Blockchain.VM { public class InvocationContext { - public UInt160 Sender { get; set; } + public readonly UInt160 Sender; public UInt256 Value => Receipt.Transaction.Value; From c4ee61f2fb5ffaa38bd9c1888b621a3517930615 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Thu, 29 Dec 2022 22:32:37 +0600 Subject: [PATCH 07/20] made sys contract addresses available --- .../ContractManager/ContractRegisterer.cs | 10 +++---- .../SystemContractAddresses.cs | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 src/Lachain.Utility/SystemContractAddresses.cs diff --git a/src/Lachain.Core/Blockchain/SystemContracts/ContractManager/ContractRegisterer.cs b/src/Lachain.Core/Blockchain/SystemContracts/ContractManager/ContractRegisterer.cs index 82d2fe053..1a168e2fa 100644 --- a/src/Lachain.Core/Blockchain/SystemContracts/ContractManager/ContractRegisterer.cs +++ b/src/Lachain.Core/Blockchain/SystemContracts/ContractManager/ContractRegisterer.cs @@ -25,11 +25,11 @@ private readonly ConcurrentDictionary _contracts private readonly IDictionary> _signatures = new Dictionary>(); - public static readonly UInt160 DeployContract = new BigInteger(0).ToUInt160(); - public static readonly UInt160 LatokenContract = new BigInteger(1).ToUInt160(); - public static readonly UInt160 GovernanceContract = new BigInteger(2).ToUInt160(); - public static readonly UInt160 StakingContract = new BigInteger(3).ToUInt160(); - public static readonly UInt160 NativeTokenContract = new BigInteger(4).ToUInt160(); + public static UInt160 DeployContract => SystemContractAddresses.DeployContract; + public static UInt160 LatokenContract => SystemContractAddresses.LatokenContract; + public static UInt160 GovernanceContract => SystemContractAddresses.GovernanceContract; + public static UInt160 StakingContract => SystemContractAddresses.StakingContract; + public static UInt160 NativeTokenContract => SystemContractAddresses.NativeTokenContract; public ContractRegisterer() { diff --git a/src/Lachain.Utility/SystemContractAddresses.cs b/src/Lachain.Utility/SystemContractAddresses.cs new file mode 100644 index 000000000..e50ffc0c1 --- /dev/null +++ b/src/Lachain.Utility/SystemContractAddresses.cs @@ -0,0 +1,26 @@ +using System.Linq; +using System.Numerics; +using Lachain.Proto; +using Lachain.Utility.Utils; + +namespace Lachain.Utility +{ + public static class SystemContractAddresses + { + public static readonly UInt160 DeployContract = new BigInteger(0).ToUInt160(); + public static readonly UInt160 LatokenContract = new BigInteger(1).ToUInt160(); + public static readonly UInt160 GovernanceContract = new BigInteger(2).ToUInt160(); + public static readonly UInt160 StakingContract = new BigInteger(3).ToUInt160(); + public static readonly UInt160 NativeTokenContract = new BigInteger(4).ToUInt160(); + + public static bool IsSystemContract(UInt160? address) + { + if (address is null) + return false; + var contracts = typeof(SystemContractAddresses).GetFields() + .Where(x => x.FieldType.Equals(typeof(UInt160)) && address.Equals(x.GetValue(x))) + .ToArray(); + return contracts.Length > 0; + } + } +} \ No newline at end of file From 95066f5b331b4fcb86bf818f698c607135511058 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Thu, 29 Dec 2022 22:32:58 +0600 Subject: [PATCH 08/20] fixed bug in configmanager --- src/Lachain.Core/Config/ConfigManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Lachain.Core/Config/ConfigManager.cs b/src/Lachain.Core/Config/ConfigManager.cs index cf9b225d2..e4c09c326 100644 --- a/src/Lachain.Core/Config/ConfigManager.cs +++ b/src/Lachain.Core/Config/ConfigManager.cs @@ -51,7 +51,7 @@ public void UpdateWalletPassword(string password) private void _UpdateConfigVersion() { ulong version = 1; - version = GetConfig("versionInfo")?.Version ?? 1; + version = GetConfig("version")?.Version ?? 1; if (version > _CurrentVersion) throw new ApplicationException("Unknown config version"); if (version == _CurrentVersion) @@ -90,7 +90,8 @@ private void _UpdateConfigVersion() _UpdateConfigToV17(); if (version < 18) _UpdateConfigToV18(); - version = GetConfig("versionInfo")?.Version ?? + System.Console.WriteLine(_CurrentVersion); + version = GetConfig("version")?.Version ?? throw new ApplicationException("No version section in config"); if (version != _CurrentVersion) throw new ApplicationException("Version not updated properly"); From 20bb34b58663d5caad7c960139d0bde9b341fca9 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 30 Dec 2022 23:57:41 +0600 Subject: [PATCH 09/20] added method to transfer allowance --- src/Lachain.Storage/State/BalanceSnapshot.cs | 13 +++++++++++++ src/Lachain.Storage/State/IBalanceSnapshot.cs | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/src/Lachain.Storage/State/BalanceSnapshot.cs b/src/Lachain.Storage/State/BalanceSnapshot.cs index da1c34502..2f7fad59c 100644 --- a/src/Lachain.Storage/State/BalanceSnapshot.cs +++ b/src/Lachain.Storage/State/BalanceSnapshot.cs @@ -131,6 +131,19 @@ public bool TransferBalance( return true; } + [MethodImpl(MethodImplOptions.Synchronized)] + public bool TransferAllowance(UInt160 from, UInt160 to, Money value, Money allowance) + { + if (allowance.CompareTo(value) < 0) // not enough allowance + return false; + var availableBalance = GetBalance(from); + if (availableBalance.CompareTo(value) < 0) + return false; + SubBalance(from, value); + AddBalance(to, value); + return true; + } + [MethodImpl(MethodImplOptions.Synchronized)] public Money MintLaToken(UInt160 address, Money value) { diff --git a/src/Lachain.Storage/State/IBalanceSnapshot.cs b/src/Lachain.Storage/State/IBalanceSnapshot.cs index 69bf58403..35a1990d2 100644 --- a/src/Lachain.Storage/State/IBalanceSnapshot.cs +++ b/src/Lachain.Storage/State/IBalanceSnapshot.cs @@ -9,6 +9,13 @@ public interface IBalanceSnapshot : ISnapshot Money GetSupply(); bool TransferBalance(UInt160 from, UInt160 to, Money value, TransactionReceipt receipt, bool checkSignature, bool useNewChainId); + /// + /// Transfers value where allowance was approved from sender. + /// Plain address balance transfer should not use this method. + /// Check if allowance was approved from sender before using this method. + /// + /// true if transferred, false otherwise + bool TransferAllowance(UInt160 from, UInt160 to, Money value, Money allowance); Money GetAllowedSupply(); void SetAllowedSupply(Money value); From e3ea19f29e233c0c2d3027fc4e02de57138efa02 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 30 Dec 2022 23:57:56 +0600 Subject: [PATCH 10/20] fixed bug --- .../SystemContracts/NativeTokenContract.cs | 76 +++---------------- .../Blockchain/VM/ExternalHandler.cs | 4 + src/Lachain.Core/Config/ConfigManager.cs | 1 - 3 files changed, 15 insertions(+), 66 deletions(-) diff --git a/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs b/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs index 2d548af06..ded9ea18c 100644 --- a/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs +++ b/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs @@ -120,6 +120,10 @@ public ExecutionStatus Transfer(UInt160 recipient, UInt256 value, SystemContract { frame.UseGas(GasMetering.NativeTokenTransferCost); var from = _context.Sender ?? throw new InvalidOperationException(); + var balance = _context.Snapshot.Balances.GetBalance(from); + Logger.LogTrace( + $"Transfer: from: {from.ToHex()} to: {recipient.ToHex()}, value: {value.ToMoney().ToString()}, balance: {balance.ToString()}" + ); bool result; if (HardforkHeights.IsHardfork_15Active(_context.Receipt.Block)) { @@ -177,73 +181,15 @@ public ExecutionStatus TransferFrom( ) { frame.UseGas(GasMetering.NativeTokenTransferFromCost); + var allowance = GetAllowance(from, Sender()).ToMoney(); + var balance = _context.Snapshot.Balances.GetBalance(from); + Logger.LogTrace( + $"TransferFrom: from: {from.ToHex()} to: {recipient.ToHex()}, value: {value.ToMoney().ToString()}, " + + $"balance: {balance.ToString()}, allowance: {allowance.ToString()}" + ); if (!SubAllowance(from, Sender(), value, frame)) return ExecutionStatus.ExecutionHalted; - bool result; - if (HardforkHeights.IsHardfork_15Active(_context.Receipt.Block)) - { - var contract = _context.Snapshot.Contracts.GetContractByHash(from); - var isSystemContract = SystemContractAddresses.IsSystemContract(from); - if ((contract is null) && !isSystemContract) - { - // balance transfer from plain address - result = _context.Snapshot.Balances.TransferBalance( - from, - recipient, - value.ToMoney(), - _context.Receipt, - HardforkHeights.IsHardfork_15Active(_context.Receipt.Block), - HardforkHeights.IsHardfork_9Active(_context.Receipt.Block) - ); - } - else if (isSystemContract) - { - // balance transfer from system contract address - // for system contract balance transfer, the sender of this invocation has to be a system contract - var sender = _context.Sender; - isSystemContract = SystemContractAddresses.IsSystemContract(sender); - if (isSystemContract) - { - result = _context.Snapshot.Balances.TransferSystemContractBalance( - from, recipient, value.ToMoney(), _context.Receipt, - HardforkHeights.IsHardfork_15Active(_context.Receipt.Block) - ); - } - else - { - // will not transfer balance of system contract - result = false; - } - - } - else - { - // balance transfer from contract address - // for this case the sender of the current invocation has to be a contract address - // and should be equal to from address - var sender = _context.Sender; - if (!(sender is null) && sender.Equals(from)) - { - result = _context.Snapshot.Balances.TransferContractBalance(from, recipient, value.ToMoney()); - } - else - { - // will not transfer balance of contract - result = false; - } - } - } - else - { - result = _context.Snapshot.Balances.TransferBalance( - from, - recipient, - value.ToMoney(), - _context.Receipt, - HardforkHeights.IsHardfork_15Active(_context.Receipt.Block), - HardforkHeights.IsHardfork_9Active(_context.Receipt.Block) - ); - } + var result = _context.Snapshot.Balances.TransferAllowance(from, recipient, value.ToMoney(), allowance); Emit(Lrc20Interface.EventTransfer, from, recipient, value); frame.ReturnValue = ContractEncoder.Encode(null, (result ? 1 : 0).ToUInt256()); if (HardforkHeights.IsHardfork_13Active(frame.InvocationContext.Snapshot.Blocks.GetTotalBlockHeight())) diff --git a/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs b/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs index 7bb71a022..1eb7ea0e7 100644 --- a/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs +++ b/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs @@ -1487,6 +1487,10 @@ private static bool TransferBalance( var receipt = frame.InvocationContext.Receipt; var snapshot = frame.InvocationContext.Snapshot; var height = snapshot.Blocks.GetTotalBlockHeight(); + var balance = snapshot.Balances.GetBalance(from); + Logger.LogTrace( + $"TransferBalance: from: {from.ToHex()}, to: {to.ToHex()}, value: {value.ToString()}, balance: {balance.ToString()}" + ); if (HardforkHeights.IsHardfork_15Active(height)) { var contract = snapshot.Contracts.GetContractByHash(from); diff --git a/src/Lachain.Core/Config/ConfigManager.cs b/src/Lachain.Core/Config/ConfigManager.cs index e4c09c326..53b5620d0 100644 --- a/src/Lachain.Core/Config/ConfigManager.cs +++ b/src/Lachain.Core/Config/ConfigManager.cs @@ -90,7 +90,6 @@ private void _UpdateConfigVersion() _UpdateConfigToV17(); if (version < 18) _UpdateConfigToV18(); - System.Console.WriteLine(_CurrentVersion); version = GetConfig("version")?.Version ?? throw new ApplicationException("No version section in config"); if (version != _CurrentVersion) From 9c640a499a84752a6725ec3980117c9c10fc699b Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 30 Dec 2022 23:58:06 +0600 Subject: [PATCH 11/20] fixed tests --- .../NativeTokenContractTest.cs | 4 +-- .../SystemContracts/StakingContractTest.cs | 17 ++++++++++-- .../IntegrationTests/TransactionsTest.cs | 4 +-- .../IntegrationTests/VirtualMachineTest.cs | 24 ++++++++--------- .../RPC/HTTP/Web3/AccountServiceWeb3Test.cs | 27 ++++++++++++++----- .../RPC/HTTP/Web3/Web3TransactionTests.cs | 10 +++---- 6 files changed, 57 insertions(+), 29 deletions(-) diff --git a/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs b/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs index c8ed50bb6..c97e6e847 100644 --- a/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs +++ b/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs @@ -93,7 +93,7 @@ public void Test_NativeTokenMinting() // set the wallet to mint the tokens { - context.Snapshot.Balances.SetBalance(address, Money.Parse("1000")); + context.Snapshot.Balances.MintLaToken(address, Money.Parse("1000")); var input = ContractEncoder.Encode(Lrc20Interface.MethodBalanceOf, address); var call = _contractRegisterer.DecodeContract(context, ContractRegisterer.NativeTokenContract, input); @@ -143,7 +143,7 @@ public void Test_NativeTokenMinting() // mint tokens to address { - context.Sender = context.Snapshot.Balances.GetMinter(); + context = context.NextContext(context.Snapshot.Balances.GetMinter()); var input = ContractEncoder.Encode(Lrc20Interface.MethodMint, address, Money.Parse("100")); var call = _contractRegisterer.DecodeContract(context, ContractRegisterer.NativeTokenContract, input); diff --git a/test/Lachain.CoreTest/Blockchain/SystemContracts/StakingContractTest.cs b/test/Lachain.CoreTest/Blockchain/SystemContracts/StakingContractTest.cs index 46537e5d5..f05be7c17 100644 --- a/test/Lachain.CoreTest/Blockchain/SystemContracts/StakingContractTest.cs +++ b/test/Lachain.CoreTest/Blockchain/SystemContracts/StakingContractTest.cs @@ -2,6 +2,7 @@ using System.IO; using System.Numerics; using System.Reflection; +using Lachain.Core.Blockchain.Hardfork; using Lachain.Core.Blockchain.Interface; using Lachain.Core.Blockchain.SystemContracts; using Lachain.Core.Blockchain.SystemContracts.ContractManager; @@ -15,6 +16,7 @@ using Lachain.Core.DI.SimpleInjector; using Lachain.Crypto; using Lachain.Crypto.ECDSA; +using Lachain.Networking; using Lachain.Proto; using Lachain.Storage.State; using Lachain.Utility; @@ -32,6 +34,7 @@ public class StakingContractTest private IStateManager _stateManager = null!; private IContractRegisterer _contractRegisterer = null!; + private IConfigManager _configManager = null!; [SetUp] public void Setup() @@ -51,6 +54,16 @@ public void Setup() _stateManager = _container.Resolve(); _contractRegisterer = _container.Resolve(); + _configManager = _container.Resolve(); + // set chainId from config + if (TransactionUtils.ChainId(false) == 0) + { + var chainId = _configManager.GetConfig("network")?.ChainId; + var newChainId = _configManager.GetConfig("network")?.NewChainId; + TransactionUtils.SetChainId((int)chainId!, (int)newChainId!); + HardforkHeights.SetHardforkHeights(_configManager.GetConfig("hardfork") ?? throw new InvalidOperationException()); + StakingContract.Initialize(_configManager.GetConfig("network")!); + } } [TearDown] @@ -63,10 +76,10 @@ public void Teardown() [Test] public void Test_OneNodeCycle() { - var tx = new TransactionReceipt(); var keyPair = new EcdsaKeyPair("0xD95D6DB65F3E2223703C5D8E205D98E3E6B470F067B0F94F6C6BF73D4301CE48" .HexToBytes().ToPrivateKey()); + var tx = TestUtils.GetRandomTransactionFromAddress(keyPair, 0, HardforkHeights.IsHardfork_9Active(0)); byte[] publicKey = CryptoUtils.EncodeCompressed(keyPair.PublicKey); var sender = keyPair.PublicKey.GetAddress(); @@ -77,7 +90,7 @@ public void Test_OneNodeCycle() // Set balance for the staker { - context.Snapshot.Balances.SetBalance(sender, Money.Parse("1000")); + context.Snapshot.Balances.MintLaToken(sender, Money.Parse("1000")); Assert.AreEqual(Money.Parse("1000"),context.Snapshot.Balances.GetBalance(sender)); } diff --git a/test/Lachain.CoreTest/IntegrationTests/TransactionsTest.cs b/test/Lachain.CoreTest/IntegrationTests/TransactionsTest.cs index fadf874bd..4a973e83e 100644 --- a/test/Lachain.CoreTest/IntegrationTests/TransactionsTest.cs +++ b/test/Lachain.CoreTest/IntegrationTests/TransactionsTest.cs @@ -207,7 +207,7 @@ public void AddRandomTxesToPool(EcdsaKeyPair keyPair, out List(); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(keyPair.PublicKey.GetAddress(), Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(keyPair.PublicKey.GetAddress(), Money.Parse("1000")); for (var i = 0; i < txCount; i++) { var tx = TestUtils.GetRandomTransactionFromAddress(keyPair, (ulong)i, useNewChainId); @@ -224,7 +224,7 @@ public void TestTxPoolAdding() var result = _transactionPool.Add(tx); Assert.AreEqual(OperatingError.InsufficientBalance, result); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(tx.Transaction.From, Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(tx.Transaction.From, Money.Parse("1000")); result = _transactionPool.Add(tx); Assert.AreEqual(OperatingError.Ok, result); diff --git a/test/Lachain.CoreTest/IntegrationTests/VirtualMachineTest.cs b/test/Lachain.CoreTest/IntegrationTests/VirtualMachineTest.cs index a87c6da39..844f0fc57 100644 --- a/test/Lachain.CoreTest/IntegrationTests/VirtualMachineTest.cs +++ b/test/Lachain.CoreTest/IntegrationTests/VirtualMachineTest.cs @@ -109,7 +109,7 @@ public void Test_VirtualMachine_InvokeMulmodContract() { var currentTime = TimeUtils.CurrentTimeMillis(); var currentSnapshot = stateManager.NewSnapshot(); - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); transactionReceipt.Transaction.Value = 0.ToUInt256(); @@ -315,7 +315,7 @@ public void Test_VirtualMachine_InvokeUniswapContract() { var currentTime = TimeUtils.CurrentTimeMillis(); var currentSnapshot = stateManager.NewSnapshot(); - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); transactionReceipt.Transaction.Value = 0.ToUInt256(); @@ -682,7 +682,7 @@ public void Test_VirtualMachine_InvokeContract() var sender = UInt160Utils.Zero; - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); @@ -753,7 +753,7 @@ public void Test_VirtualMachine_InvokeAllFeaturesContract() var sender = "0x6bc32575acb8754886dc283c2c8ac54b1bd93195".HexToBytes().ToUInt160(); - currentSnapshot.Balances.AddBalance(sender, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(sender, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); @@ -987,7 +987,7 @@ public void Test_VirtualMachine_InvokeContractWithValue() var sender = UInt160Utils.Zero; - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); @@ -1114,8 +1114,8 @@ public void Test_VirtualMachine_InvokeCreateContract() var sender = UInt160Utils.Zero; - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); - currentSnapshot.Balances.AddBalance(aAddress, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(aAddress, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); @@ -1204,8 +1204,8 @@ public void Test_VirtualMachine_InvokeStringContract() var sender = UInt160Utils.Zero; - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); - currentSnapshot.Balances.AddBalance(aAddress, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(aAddress, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); @@ -1291,7 +1291,7 @@ public void Test_VirtualMachine_InvokeDelegateContract() var sender = UInt160Utils.Zero; - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); @@ -1424,7 +1424,7 @@ public void Test_VirtualMachine_InvokeStaticContract() var sender = UInt160Utils.Zero; - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); @@ -1925,7 +1925,7 @@ public void Test_VirtualMachine_InvokeCallingContract() var currentTime = TimeUtils.CurrentTimeMillis(); var currentSnapshot = stateManager.NewSnapshot(); var sender = UInt160Utils.Zero; - currentSnapshot.Balances.AddBalance(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); + currentSnapshot.Balances.MintLaToken(UInt160Utils.Zero, 100.ToUInt256().ToMoney()); var transactionReceipt = new TransactionReceipt(); transactionReceipt.Transaction = new Transaction(); transactionReceipt.Transaction.Value = 0.ToUInt256(); diff --git a/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs b/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs index 365dd6d45..f49cec1a8 100644 --- a/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs +++ b/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs @@ -123,13 +123,18 @@ public void TestGetBalance() { var address = "0x6bc32575acb8754886dc283c2c8ac54b1bd93195"; var bal = _apiService.GetBalance(address, "latest"); - Assert.AreEqual(bal, "0x84595161401484a000000"); + var prevBalance = "0x84595161401484a000000"; + Assert.AreEqual(bal, prevBalance); //updating balance - _stateManager.LastApprovedSnapshot.Balances.SetBalance(address.HexToBytes().ToUInt160(), Money.Parse("90000000000000000")); + var balanceAdded = Money.Parse("90000000000000000"); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(address.HexToBytes().ToUInt160(), balanceAdded); + var formatedBalance = FormatHex(prevBalance); + System.Console.WriteLine(formatedBalance); + var totalBalance = balanceAdded + new Money(formatedBalance.HexToUInt256(true)); var balNew = _apiService.GetBalance(address, "latest"); - Assert.AreEqual(balNew, "0x115557b419c5c1f3fa018400000000"); + Assert.AreEqual(balNew, Web3DataFormatUtils.Web3Number(totalBalance.ToUInt256())); } [Test] @@ -138,7 +143,7 @@ public void TestGetBalancePending() { var tx = TestUtils.GetRandomTransaction(false); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(tx.Transaction.From, Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(tx.Transaction.From, Money.Parse("1000")); var result = _transactionPool.Add(tx); Assert.AreEqual(OperatingError.Ok, result); @@ -171,7 +176,7 @@ public void Test_GetTransactionCount_latest() _blockManager.TryBuildGenesisBlock(); var tx = TestUtils.GetRandomTransaction(HardforkHeights.IsHardfork_9Active(1)); // adding balance so that it's transaction is added to the pool - _stateManager.LastApprovedSnapshot.Balances.AddBalance(tx.Transaction.From, Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(tx.Transaction.From, Money.Parse("1000")); @@ -345,7 +350,7 @@ private void ExecuteDummyTransaction(bool generateblock, string rawTx) var sender = ethTx.Key.GetPublicAddress().HexToBytes().ToUInt160(); // Updating balance of sender's Wallet - _stateManager.LastApprovedSnapshot.Balances.SetBalance(sender, Money.Parse("90000000000000000")); + // _stateManager.LastApprovedSnapshot.Balances.SetBalance(sender, Money.Parse("90000000000000000")); if (generateblock) { @@ -354,6 +359,16 @@ private void ExecuteDummyTransaction(bool generateblock, string rawTx) } + private string FormatHex(string hexString) + { + if (hexString.Length % 2 == 0) return hexString; + if (hexString.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase)) + { + return "0x0" + hexString.Substring(2); + } + else return "0" + hexString; + } + private void GenerateBlocks(ulong blockNum) { for (ulong i = 1; i <= blockNum; i++) diff --git a/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs b/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs index f94e60fd0..b1a4c1be8 100644 --- a/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs +++ b/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs @@ -201,7 +201,7 @@ public void Test_GetTransactionReceipt() { _blockManager.TryBuildGenesisBlock(); var tx = TestUtils.GetRandomTransaction(HardforkHeights.IsHardfork_9Active(1)); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(tx.Transaction.From, Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(tx.Transaction.From, Money.Parse("1000")); var result = _transactionPool.Add(tx); Assert.AreEqual(OperatingError.Ok, result); GenerateBlocks(1, 1); @@ -217,7 +217,7 @@ public void Test_GetTransactionByHash() { _blockManager.TryBuildGenesisBlock(); var tx = TestUtils.GetRandomTransaction(HardforkHeights.IsHardfork_9Active(1)); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(tx.Transaction.From, Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(tx.Transaction.From, Money.Parse("1000")); var result = _transactionPool.Add(tx); Assert.AreEqual(OperatingError.Ok, result); GenerateBlocks(1, 1); @@ -236,7 +236,7 @@ public void Test_GetTransactionByBlockHashAndIndex() { _blockManager.TryBuildGenesisBlock(); var tx = TestUtils.GetRandomTransaction(HardforkHeights.IsHardfork_9Active(1)); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(tx.Transaction.From, Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(tx.Transaction.From, Money.Parse("1000")); var result = _transactionPool.Add(tx); Assert.AreEqual(OperatingError.Ok, result); GenerateBlocks(1, 1); @@ -260,7 +260,7 @@ public void Test_GetTransactionByBlockNumberAndIndex() _blockManager.TryBuildGenesisBlock(); var tx = TestUtils.GetRandomTransaction(HardforkHeights.IsHardfork_9Active(1)); - _stateManager.LastApprovedSnapshot.Balances.AddBalance(tx.Transaction.From, Money.Parse("1000")); + _stateManager.LastApprovedSnapshot.Balances.MintLaToken(tx.Transaction.From, Money.Parse("1000")); var result = _transactionPool.Add(tx); Assert.AreEqual(OperatingError.Ok, result); GenerateBlocks(1, 1); @@ -404,7 +404,7 @@ private String Execute_dummy_transaction(String rawTx) var sender = ethTx.Key.GetPublicAddress().HexToBytes().ToUInt160(); // Updating balance of sender's Wallet - _stateManager.LastApprovedSnapshot.Balances.SetBalance(sender, Money.Parse("90000000000000000")); + // _stateManager.LastApprovedSnapshot.Balances.SetBalance(sender, Money.Parse("90000000000000000")); GenerateBlocks(1, 1); From c48315fced4a4f33d74684583ea540739ef50d11 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Tue, 3 Jan 2023 23:38:21 +0600 Subject: [PATCH 12/20] added test --- .../NativeTokenContractTest.cs | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs b/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs index c97e6e847..e8adb999b 100644 --- a/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs +++ b/test/Lachain.CoreTest/Blockchain/SystemContracts/NativeTokenContractTest.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Reflection; +using Lachain.Core.Blockchain.Hardfork; using Lachain.Core.Blockchain.Interface; using Lachain.Core.Blockchain.SystemContracts; using Lachain.Core.Blockchain.SystemContracts.ContractManager; @@ -14,6 +15,7 @@ using Lachain.Core.DI.SimpleInjector; using Lachain.Crypto; using Lachain.Crypto.ECDSA; +using Lachain.Networking; using Lachain.Proto; using Lachain.Storage.State; using Lachain.Utility; @@ -28,6 +30,8 @@ public class NativeTokenContractTest private IContainer? _container; private IStateManager _stateManager = null!; + private IBlockManager _blockManager = null!; + private IConfigManager _configManager = null!; private IContractRegisterer _contractRegisterer = null!; private EcdsaKeyPair _minterKeyPair = null!; @@ -57,6 +61,8 @@ public void Setup() _stateManager = _container.Resolve(); _contractRegisterer = _container.Resolve(); + _blockManager = _container.Resolve(); + _configManager = _container.Resolve(); _minterKeyPair = new EcdsaKeyPair("0xD95D6DB65F3E2223703C5D8E205D98E3E6B470F067B0F94F6C6BF73D4301CE48" .HexToBytes().ToPrivateKey()); @@ -67,6 +73,15 @@ public void Setup() .ToPrivateKey()); _mintCntrlPubKey = CryptoUtils.EncodeCompressed(_mintCntrlKeyPair.PublicKey); _mintCntrlAdd = _mintCntrlKeyPair.PublicKey.GetAddress(); + // set chainId from config + if (TransactionUtils.ChainId(false) == 0) + { + var chainId = _configManager.GetConfig("network")?.ChainId; + var newChainId = _configManager.GetConfig("network")?.NewChainId; + TransactionUtils.SetChainId((int)chainId!, (int)newChainId!); + HardforkHeights.SetHardforkHeights(_configManager.GetConfig("hardfork") ?? throw new InvalidOperationException()); + StakingContract.Initialize(_configManager.GetConfig("network")!); + } } [TearDown] @@ -352,5 +367,51 @@ public void Test_SetMinterInvalidMintCtlr() Assert.AreEqual(ExecutionStatus.ExecutionHalted, contract.SetMinter(_minterAdd, frame)); } } + + [Test] + public void Test_TokenTransfer() + { + _blockManager.TryBuildGenesisBlock(); + var useNewChainId = HardforkHeights.IsHardfork_9Active(0); + var tx = TestUtils.GetRandomTransactionFromAddress(_minterKeyPair, 0, useNewChainId); + + // token transfer + { + var res = _stateManager.LastApprovedSnapshot.Balances.TransferBalance( + tx.Transaction.From, tx.Transaction.To, tx.Transaction.Value.ToMoney(), tx, true, useNewChainId + ); + Assert.That(res); + } + + // invalid token transfer + { + var res = _stateManager.LastApprovedSnapshot.Balances.TransferBalance( + TestUtils.GetRandomBytes(20).ToUInt160(), tx.Transaction.To, tx.Transaction.Value.ToMoney(), tx, true, useNewChainId + ); + Assert.IsFalse(res); + } + + // token transfer method + { + var context = new InvocationContext(tx.Transaction.From, _stateManager.LastApprovedSnapshot, tx); + var contract = new NativeTokenContract(context); + var input = ContractEncoder.Encode(Lrc20Interface.MethodTransfer, tx.Transaction.To, tx.Transaction.Value); + var call = _contractRegisterer.DecodeContract(context, ContractRegisterer.NativeTokenContract, input); + Assert.IsNotNull(call); + var frame = new SystemContractExecutionFrame(call!, context, input, 100_000_000); + Assert.AreEqual(ExecutionStatus.Ok, contract.Transfer(tx.Transaction.To, tx.Transaction.Value, frame)); + } + + // invalid token transfer method + { + var context = new InvocationContext(TestUtils.GetRandomBytes(20).ToUInt160(), _stateManager.LastApprovedSnapshot, tx); + var contract = new NativeTokenContract(context); + var input = ContractEncoder.Encode(Lrc20Interface.MethodTransfer, tx.Transaction.To, tx.Transaction.Value); + var call = _contractRegisterer.DecodeContract(context, ContractRegisterer.NativeTokenContract, input); + Assert.IsNotNull(call); + var frame = new SystemContractExecutionFrame(call!, context, input, 100_000_000); + Assert.AreEqual(ExecutionStatus.ExecutionHalted, contract.Transfer(tx.Transaction.To, tx.Transaction.Value, frame)); + } + } } } \ No newline at end of file From 3aab1205fd5fb1ccfefcc426e9535abf3fd51c8d Mon Sep 17 00:00:00 2001 From: tbssajal Date: Tue, 3 Jan 2023 23:39:22 +0600 Subject: [PATCH 13/20] added balance snapshot for no verification --- .../State/NoVerificationBalanceSnapshot.cs | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 src/Lachain.Storage/State/NoVerificationBalanceSnapshot.cs diff --git a/src/Lachain.Storage/State/NoVerificationBalanceSnapshot.cs b/src/Lachain.Storage/State/NoVerificationBalanceSnapshot.cs new file mode 100644 index 000000000..f0d00d9f5 --- /dev/null +++ b/src/Lachain.Storage/State/NoVerificationBalanceSnapshot.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using Lachain.Crypto; +using Lachain.Logger; +using Lachain.Proto; +using Lachain.Storage.DbCompact; +using Lachain.Storage.Trie; +using Lachain.Utility; +using Lachain.Utility.Utils; + +namespace Lachain.Storage.State +{ + /* + Balance Snapshot is basically a HMAT (trie) and it stores the balance of all the address. + You can think of it as a key-value storage of (address -> balance). + */ + public class NoVerificationBalanceSnapshot : IBalanceSnapshot + { + private static readonly ILogger Logger + = LoggerFactory.GetLoggerForClass(); + private readonly IStorageState _state; + private static readonly ICrypto Crypto = CryptoProvider.GetCrypto(); + + public NoVerificationBalanceSnapshot(IStorageState state) + { + _state = state; + } + + public IDictionary GetState() + { + return _state.GetAllNodes(); + } + + public bool IsTrieNodeHashesOk() + { + return _state.IsNodeHashesOk(); + } + + public ulong SetState(ulong root, IDictionary allTrieNodes) + { + return _state.InsertAllNodes(root, allTrieNodes); + } + + public ulong Version => _state.CurrentVersion; + + public uint RepositoryId => _state.RepositoryId; + + [MethodImpl(MethodImplOptions.Synchronized)] + public Money GetBalance(UInt160 owner) + { + var key = EntryPrefix.BalanceByOwnerAndAsset.BuildPrefix(owner); + var value = _state.Get(key); + var balance = value?.ToUInt256() ?? UInt256Utils.Zero; + return new Money(balance); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public Money GetSupply() + { + var key = EntryPrefix.TotalSupply.BuildPrefix(); + var value = _state.Get(key); + var supply = value?.ToUInt256() ?? UInt256Utils.Zero; + return new Money(supply); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private void SetBalance(UInt160 owner, Money value) + { + var key = EntryPrefix.BalanceByOwnerAndAsset.BuildPrefix(owner); + _state.AddOrUpdate(key, value.ToUInt256().ToBytes()); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private void SetSupply(Money value) + { + var key = EntryPrefix.TotalSupply.BuildPrefix(); + _state.AddOrUpdate(key, value.ToUInt256().ToBytes()); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private Money AddBalance(UInt160 owner, Money value, bool increaseSupply = false) + { + var balance = GetBalance(owner); + balance += value; + SetBalance(owner, balance); + if (increaseSupply) + { + var supply = GetSupply(); + supply += value; + SetSupply(supply); + } + + return balance; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private Money SubBalance(UInt160 owner, Money value) + { + var balance = GetBalance(owner); + balance -= value; + SetBalance(owner, balance); + return balance; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public bool TransferBalance( + UInt160 from, UInt160 to, Money value, TransactionReceipt receipt, bool checkSignature, bool useNewChainId + ) + { + var availableBalance = GetBalance(from); + if (availableBalance.CompareTo(value) < 0) + return false; + if (checkSignature) + { + // never check signature because this snapshot bypasses verification + } + SubBalance(from, value); + AddBalance(to, value); + return true; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public bool TransferAllowance(UInt160 from, UInt160 to, Money value, Money allowance) + { + if (allowance.CompareTo(value) < 0) // not enough allowance + return false; + var availableBalance = GetBalance(from); + if (availableBalance.CompareTo(value) < 0) + return false; + SubBalance(from, value); + AddBalance(to, value); + return true; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public Money MintLaToken(UInt160 address, Money value) + { + return AddBalance(address, value, true); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public Money GetAllowedSupply() + { + var key = EntryPrefix.AllowedSupply.BuildPrefix(); + var value = _state.Get(key); + var supply = value?.ToUInt256() ?? UInt256Utils.Zero; + return new Money(supply); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public void SetAllowedSupply(Money value) + { + var key = EntryPrefix.AllowedSupply.BuildPrefix(); + _state.AddOrUpdate(key, value.ToUInt256().ToBytes()); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public UInt160 GetMinter() + { + var key = EntryPrefix.MinterAddress.BuildPrefix(); + var value = _state.Get(key); + + if (value == null) + return UInt160Utils.Zero; + + var address = value?.ToUInt160() ?? UInt160Utils.Zero; + return address; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public void SetMinter(UInt160 value) + { + var key = EntryPrefix.MinterAddress.BuildPrefix(); + _state.AddOrUpdate(key, value.ToBytes()); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public Money RemoveCollectedFees(Money fee, TransactionReceipt receipt) + { + if (!receipt.Transaction.From.Equals(UInt160Utils.Zero)) + throw new Exception($"Non system contract transaction {receipt.Hash.ToHex()} requests RemoveCollectedFees"); + return SubBalance(SystemContractAddresses.GovernanceContract, fee); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public bool TransferContractBalance(UInt160 from, UInt160 to, Money value) + { + var availableBalance = GetBalance(from); + if (availableBalance.CompareTo(value) < 0) + return false; + SubBalance(from, value); + AddBalance(to, value); + return true; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public bool TransferSystemContractBalance( + UInt160 from, UInt160 to, Money value, TransactionReceipt receipt, bool checkVerification + ) + { + if (checkVerification) + { + // never check signature because this snapshot bypasses verification + } + var availableBalance = GetBalance(from); + if (availableBalance.CompareTo(value) < 0) + return false; + SubBalance(from, value); + AddBalance(to, value); + return true; + } + + public void Commit(RocksDbAtomicWrite batch) + { + throw new NotImplementedException( + "NoVerificationBalanceSnapshot cannot commit to state because we bypass verification, so we cannot change state" + ); + } + public void SetCurrentVersion(ulong root) + { + _state.SetCurrentVersion(root); + } + public void ClearCache() + { + _state.ClearCache(); + } + public UInt256 Hash => _state.Hash; + + public ulong SaveNodeId(IDbShrinkRepository _repo) + { + return _state.SaveNodeId(_repo); + } + + } +} \ No newline at end of file From 0481e1ec776f919c0cbbdf0d658b49c4144ec306 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Thu, 5 Jan 2023 02:17:42 +0600 Subject: [PATCH 14/20] added state simulator without commit --- src/Lachain.Storage/State/StateSimulator.cs | 193 ++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 src/Lachain.Storage/State/StateSimulator.cs diff --git a/src/Lachain.Storage/State/StateSimulator.cs b/src/Lachain.Storage/State/StateSimulator.cs new file mode 100644 index 000000000..6e0d5bcf7 --- /dev/null +++ b/src/Lachain.Storage/State/StateSimulator.cs @@ -0,0 +1,193 @@ +using System; +using System.Threading; +using Lachain.Logger; + +namespace Lachain.Storage.State +{ + /* + This is the main class the core part utilizes to make any changes to the state of the blockchain. + There are 3 layers of snapshot, + (1) Committed Snapshot - this snapshot already persists in disk + (2) Approved Snapshot - approved but may not persist in the disk + (3) Pending Snapshot - this is not yet approved + + To make any changes to the state, it's required to + (1) create a new snapshot, (2) make changes to the snapshot + (3) either approve or rollback() + approving adds all the changes to the lastApprovedSnapshot + and rollback() discards all the changes and lastApprovedSnapshot is not changed + + Always write to state inside safe context to avoid concurrency issues. + */ + public class StateSimulator : IStateManager + { + private static readonly ILogger Logger = LoggerFactory.GetLoggerForClass(); + public IBlockchainSnapshot CurrentSnapshot => PendingSnapshot ?? LastApprovedSnapshot; + + public IBlockchainSnapshot LastApprovedSnapshot { get; private set; } + public IBlockchainSnapshot? PendingSnapshot { get; private set; } + + private readonly ISnapshotManager _blockManager; + private readonly ISnapshotManager _transactionManager; + private readonly ISnapshotManager _balanceManager; + private readonly ISnapshotManager _contractManager; + private readonly ISnapshotManager _storageManager; + private readonly ISnapshotManager _eventManager; + private readonly ISnapshotManager _validatorManager; + + private readonly Mutex _globalMutex = new Mutex(false); + + public StateSimulator(IStorageManager storageManager) + { + _balanceManager = + new SnapshotManager(storageManager, + (uint) RepositoryType.BalanceRepository); + _contractManager = + new SnapshotManager(storageManager, + (uint) RepositoryType.ContractRepository); + _storageManager = + new SnapshotManager(storageManager, + (uint) RepositoryType.StorageRepository); + _transactionManager = + new SnapshotManager(storageManager, + (uint) RepositoryType.TransactionRepository); + _blockManager = + new SnapshotManager(storageManager, + (uint) RepositoryType.BlockRepository); + _eventManager = + new SnapshotManager(storageManager, + (uint) RepositoryType.EventRepository); + _validatorManager = + new SnapshotManager(storageManager, + (uint) RepositoryType.ValidatorRepository); + + LastApprovedSnapshot = new BlockchainSnapshot( + _balanceManager.LastApprovedSnapshot, + _contractManager.LastApprovedSnapshot, + _storageManager.LastApprovedSnapshot, + _transactionManager.LastApprovedSnapshot, + _blockManager.LastApprovedSnapshot, + _eventManager.LastApprovedSnapshot, + _validatorManager.LastApprovedSnapshot + ); + } + + public void SafeContext(Action callback) + { + try + { + Acquire(); + callback.Invoke(); + } + finally + { + Release(); + } + } + + public T SafeContext(Func callback) + { + try + { + Acquire(); + return callback.Invoke(); + } + finally + { + Release(); + } + } + + public void Acquire() + { + _globalMutex.WaitOne(); + } + + public void Release() + { + if (PendingSnapshot != null) + { + Logger.LogError("Nonzero pending snapshot on exit from SafeContext"); + Rollback(); + } + _globalMutex.ReleaseMutex(); + } + + public IBlockchainSnapshot NewSnapshot() + { + if (PendingSnapshot != null) + throw new InvalidOperationException("Cannot begin new snapshot, need to approve or rollback first"); + PendingSnapshot = new BlockchainSnapshot( + _balanceManager.NewSnapshot(), + _contractManager.NewSnapshot(), + _storageManager.NewSnapshot(), + _transactionManager.NewSnapshot(), + _blockManager.NewSnapshot(), + _eventManager.NewSnapshot(), + _validatorManager.NewSnapshot() + ); + return PendingSnapshot; + } + + public void Approve() + { + _balanceManager.Approve(); + _contractManager.Approve(); + _storageManager.Approve(); + _transactionManager.Approve(); + _blockManager.Approve(); + _eventManager.Approve(); + _validatorManager.Approve(); + LastApprovedSnapshot = PendingSnapshot ?? throw new InvalidOperationException("Nothing to approve"); + PendingSnapshot = null; + } + + public void Rollback() + { + if (PendingSnapshot == null) + throw new InvalidOperationException("Nothing to rollback"); + _balanceManager.Rollback(); + _contractManager.Rollback(); + _storageManager.Rollback(); + _transactionManager.Rollback(); + _blockManager.Rollback(); + _eventManager.Rollback(); + _validatorManager.Rollback(); + PendingSnapshot = null; + } + + public void Commit() + { + throw new NotImplementedException("StateSimulator cannot commit to state"); + } + + public void ClearCache() + { + _balanceManager.ClearCache(); + _contractManager.ClearCache(); + _storageManager.ClearCache(); + _transactionManager.ClearCache(); + _blockManager.ClearCache(); + _eventManager.ClearCache(); + _validatorManager.ClearCache(); + } + public void Commit(RocksDbAtomicWrite batch) + { + throw new Exception("Invalid function used"); + } + + public void RollbackTo(IBlockchainSnapshot snapshot) + { + if (PendingSnapshot != null) + throw new InvalidOperationException("Cannot rollback to state with unapproved changes"); + _balanceManager.RollbackTo(snapshot.Balances); + _contractManager.RollbackTo(snapshot.Contracts); + _storageManager.RollbackTo(snapshot.Storage); + _transactionManager.RollbackTo(snapshot.Transactions); + _blockManager.RollbackTo(snapshot.Blocks); + _eventManager.RollbackTo(snapshot.Events); + _validatorManager.RollbackTo(snapshot.Validators); + LastApprovedSnapshot = snapshot; + } + } +} \ No newline at end of file From 35bc05b523f4e7b62d5245cde60489cc17a072ae Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 6 Jan 2023 00:19:38 +0600 Subject: [PATCH 15/20] added equals and hash code --- src/Lachain.Storage/Trie/IHashTrieNode.cs | 5 +++-- src/Lachain.Storage/Trie/InternalNode.cs | 17 +++++++++++++++++ src/Lachain.Storage/Trie/LeafNode.cs | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Lachain.Storage/Trie/IHashTrieNode.cs b/src/Lachain.Storage/Trie/IHashTrieNode.cs index 5a7a5a24b..ceba5424c 100644 --- a/src/Lachain.Storage/Trie/IHashTrieNode.cs +++ b/src/Lachain.Storage/Trie/IHashTrieNode.cs @@ -1,8 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Lachain.Storage.Trie { - public interface IHashTrieNode + public interface IHashTrieNode : IEquatable { NodeType Type { get; } diff --git a/src/Lachain.Storage/Trie/InternalNode.cs b/src/Lachain.Storage/Trie/InternalNode.cs index 9b58d7ade..1c877612e 100644 --- a/src/Lachain.Storage/Trie/InternalNode.cs +++ b/src/Lachain.Storage/Trie/InternalNode.cs @@ -132,5 +132,22 @@ public static InternalNode WithChildren( newNode.UpdateHash(newHashes, GetChildrenLabels(newNode.ChildrenMask)); return newNode; } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((IHashTrieNode) obj); + } + + public bool Equals(IHashTrieNode? other) + { + return !(other is null) && Hash.SequenceEqual(other.Hash); + } + + public override int GetHashCode() + { + return Hash.Length; + } } } \ No newline at end of file diff --git a/src/Lachain.Storage/Trie/LeafNode.cs b/src/Lachain.Storage/Trie/LeafNode.cs index f12f0f440..0abf5cdcf 100644 --- a/src/Lachain.Storage/Trie/LeafNode.cs +++ b/src/Lachain.Storage/Trie/LeafNode.cs @@ -27,5 +27,22 @@ public ulong GetChildByHash(byte h) } public IEnumerable Children { get; } = Enumerable.Empty(); + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj.GetType() == GetType() && Equals((IHashTrieNode) obj); + } + + public bool Equals(IHashTrieNode? other) + { + return !(other is null) && Hash.SequenceEqual(other.Hash); + } + + public override int GetHashCode() + { + return Hash.Length; + } } } \ No newline at end of file From f7b1b68b15cc6e78a73932f189e9f5f806071818 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 6 Jan 2023 00:20:05 +0600 Subject: [PATCH 16/20] using state simulator --- .../RPC/HTTP/Web3/TransactionServiceWeb3.cs | 33 +++++++++++-------- src/Lachain.Core/RPC/RpcManager.cs | 6 +++- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/Lachain.Core/RPC/HTTP/Web3/TransactionServiceWeb3.cs b/src/Lachain.Core/RPC/HTTP/Web3/TransactionServiceWeb3.cs index a80e6533e..0e302b0ad 100644 --- a/src/Lachain.Core/RPC/HTTP/Web3/TransactionServiceWeb3.cs +++ b/src/Lachain.Core/RPC/HTTP/Web3/TransactionServiceWeb3.cs @@ -18,6 +18,7 @@ using Lachain.Crypto; using Lachain.Logger; using Lachain.Proto; +using Lachain.Storage; using Lachain.Storage.State; using Lachain.Utility.Serialization; using Lachain.Utility.Utils; @@ -37,6 +38,7 @@ public class TransactionServiceWeb3 : JsonRpcService LoggerFactory.GetLoggerForClass(); private readonly IStateManager _stateManager; + private readonly IStorageManager _storageManager; private readonly ITransactionManager _transactionManager; private readonly ITransactionBuilder _transactionBuilder; private readonly ITransactionSigner _transactionSigner; @@ -47,6 +49,7 @@ public class TransactionServiceWeb3 : JsonRpcService public TransactionServiceWeb3( + IStorageManager storageManager, IStateManager stateManager, ITransactionManager transactionManager, ITransactionBuilder transactionBuilder, @@ -64,6 +67,7 @@ public TransactionServiceWeb3( _contractRegisterer = contractRegisterer; _privateWallet = privateWallet; _blockManager = blockManager; + _storageManager = storageManager; } public Transaction MakeTransaction(LegacyTransactionChainId ethTx) @@ -404,6 +408,7 @@ public string Call(JObject opts, string? blockId) public string? EstimateGas(JObject opts) { Logger.LogInformation($"eth_estimateGas({opts})"); + IStateManager stateSimulator = new StateSimulator(_storageManager); var gasUsed = GasMetering.DefaultTxCost; var from = opts["from"]; var to = opts["to"]; @@ -422,11 +427,11 @@ public string Call(JObject opts, string? blockId) if (to is null) // deploy contract { if (!VirtualMachine.VerifyContract(invocation, - HardforkHeights.IsHardfork_2Active(_stateManager.LastApprovedSnapshot.Blocks.GetTotalBlockHeight()))) + HardforkHeights.IsHardfork_2Active(stateSimulator.LastApprovedSnapshot.Blocks.GetTotalBlockHeight()))) throw new ArgumentException("Unable to validate smart-contract code"); - InvocationResult invRes = _stateManager.SafeContext(() => + InvocationResult invRes = stateSimulator.SafeContext(() => { - var snapshot = _stateManager.NewSnapshot(); + var snapshot = stateSimulator.NewSnapshot(); var context = new InvocationContext(source, snapshot, new TransactionReceipt { Block = snapshot.Blocks.GetTotalBlockHeight(), @@ -442,7 +447,7 @@ public string Call(JObject opts, string? blockId) invocation, GasMetering.DefaultBlockGasLimit ); - _stateManager.Rollback(); + stateSimulator.Rollback(); return res; }); if (invRes.Status == ExecutionStatus.Ok) @@ -459,14 +464,14 @@ public string Call(JObject opts, string? blockId) throw new RpcException(RpcErrorCode.Warning,$"Error in systen contract call: {invRes.Status.ToString()}"); } - var contract = _stateManager.LastApprovedSnapshot.Contracts.GetContractByHash(destination); + var contract = stateSimulator.LastApprovedSnapshot.Contracts.GetContractByHash(destination); var systemContract = _contractRegisterer.GetContractByAddress(destination); if (contract is null && systemContract is null) { - InvocationResult transferInvRes = _stateManager.SafeContext(() => + InvocationResult transferInvRes = stateSimulator.SafeContext(() => { - var snapshot = _stateManager.NewSnapshot(); + var snapshot = stateSimulator.NewSnapshot(); var systemContractContext = new InvocationContext(source, snapshot, new TransactionReceipt { Block = snapshot.Blocks.GetTotalBlockHeight(), @@ -476,7 +481,7 @@ public string Call(JObject opts, string? blockId) var localInvocation = ContractEncoder.Encode("transfer(address,uint256)", source, 0.ToUInt256()); var invocationResult = ContractInvoker.Invoke(ContractRegisterer.LatokenContract, systemContractContext, localInvocation, GasMetering.DefaultBlockGasLimit); - _stateManager.Rollback(); + stateSimulator.Rollback(); return invocationResult; }); @@ -488,9 +493,9 @@ public string Call(JObject opts, string? blockId) if (!(contract is null)) { - InvocationResult invRes = _stateManager.SafeContext(() => + InvocationResult invRes = stateSimulator.SafeContext(() => { - var snapshot = _stateManager.NewSnapshot(); + var snapshot = stateSimulator.NewSnapshot(); if (!tx.Value.IsZero()) { var transferContext = new InvocationContext(source, snapshot, new TransactionReceipt @@ -516,7 +521,7 @@ public string Call(JObject opts, string? blockId) invocation, GasMetering.DefaultBlockGasLimit ); - _stateManager.Rollback(); + stateSimulator.Rollback(); return res; }); if (invRes.Status == ExecutionStatus.Ok) @@ -533,9 +538,9 @@ public string Call(JObject opts, string? blockId) throw new RpcException(RpcErrorCode.Warning,$"Error in contract call {invRes.Status.ToString()}"); } - InvocationResult systemContractInvRes = _stateManager.SafeContext(() => + InvocationResult systemContractInvRes = stateSimulator.SafeContext(() => { - var snapshot = _stateManager.NewSnapshot(); + var snapshot = stateSimulator.NewSnapshot(); if (!tx.Value.IsZero()) { var transferContext = new InvocationContext(source, snapshot, new TransactionReceipt @@ -559,7 +564,7 @@ public string Call(JObject opts, string? blockId) var invocationResult = ContractInvoker.Invoke(destination, systemContractContext, invocation, GasMetering.DefaultBlockGasLimit); - _stateManager.Rollback(); + stateSimulator.Rollback(); return invocationResult; }); diff --git a/src/Lachain.Core/RPC/RpcManager.cs b/src/Lachain.Core/RPC/RpcManager.cs index a5b391bc9..70c8c14a8 100644 --- a/src/Lachain.Core/RPC/RpcManager.cs +++ b/src/Lachain.Core/RPC/RpcManager.cs @@ -11,6 +11,7 @@ using Lachain.Core.ValidatorStatus; using Lachain.Core.Vault; using Lachain.Networking; +using Lachain.Storage; using Lachain.Storage.Repositories; using Lachain.Storage.State; using Lachain.Storage.Trie; @@ -24,6 +25,7 @@ public class RpcManager : IRpcManager private readonly IBlockManager _blockManager; private readonly IConfigManager _configManager; private readonly IStateManager _stateManager; + private readonly IStorageManager _storageManager; private readonly ISnapshotIndexRepository _snapshotIndexer; private readonly IPrivateWallet _privateWallet; private readonly ITransactionSigner _transactionSigner; @@ -40,6 +42,7 @@ public class RpcManager : IRpcManager public RpcManager( + IStorageManager storageManager, ITransactionManager transactionManager, IBlockManager blockManager, IConfigManager configManager, @@ -61,6 +64,7 @@ public RpcManager( IConsensusManager consensusManager ) { + _storageManager = storageManager; _transactionManager = transactionManager; _blockManager = blockManager; _configManager = configManager; @@ -95,7 +99,7 @@ public void Start() new BlockchainServiceWeb3(_transactionManager, _blockManager, _transactionPool, _stateManager, _snapshotIndexer, _networkManager, _nodeRetrieval, _systemContractReader, _consensusManager), new AccountServiceWeb3(_stateManager, _snapshotIndexer, _contractRegisterer, _systemContractReader, _transactionPool), new ValidatorServiceWeb3(_validatorStatusManager, _privateWallet, _transactionBuilder), - new TransactionServiceWeb3(_stateManager, _transactionManager, _transactionBuilder, _transactionSigner, + new TransactionServiceWeb3(_storageManager, _stateManager, _transactionManager, _transactionBuilder, _transactionSigner, _transactionPool, _contractRegisterer, _privateWallet, _blockManager), new FrontEndService(_stateManager, _transactionPool, _transactionSigner, _systemContractReader, _localTransactionRepository, _validatorStatusManager, _privateWallet, _transactionManager), From f9bc5781e42a205491e7a399219357b8e798e2bb Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 6 Jan 2023 00:22:36 +0600 Subject: [PATCH 17/20] updated tests --- .../IntegrationTests/StorageSimulatorTest.cs | 369 ++++++++++++++++++ .../RPC/HTTP/Web3/AccountServiceWeb3Test.cs | 41 +- .../RPC/HTTP/Web3/Web3TransactionTests.cs | 19 +- 3 files changed, 402 insertions(+), 27 deletions(-) create mode 100644 test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs diff --git a/test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs b/test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs new file mode 100644 index 000000000..ef3d85ce6 --- /dev/null +++ b/test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs @@ -0,0 +1,369 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Google.Protobuf; +using Lachain.Consensus; +using Lachain.Core.Blockchain.Error; +using Lachain.Core.Blockchain.Hardfork; +using Lachain.Core.Blockchain.Interface; +using Lachain.Core.Blockchain.Operations; +using Lachain.Core.Blockchain.Pool; +using Lachain.Core.Blockchain.SystemContracts; +using Lachain.Core.Blockchain.SystemContracts.ContractManager; +using Lachain.Core.Blockchain.SystemContracts.Interface; +using Lachain.Core.Blockchain.VM; +using Lachain.Core.CLI; +using Lachain.Core.Config; +using Lachain.Core.DI; +using Lachain.Core.DI.Modules; +using Lachain.Core.DI.SimpleInjector; +using Lachain.Core.Vault; +using Lachain.Crypto; +using Lachain.Crypto.ECDSA; +using Lachain.Crypto.Misc; +using Lachain.Logger; +using Lachain.Networking; +using Lachain.Proto; +using Lachain.Storage; +using Lachain.Storage.State; +using Lachain.Storage.Trie; +using Lachain.Utility; +using Lachain.Utility.Utils; +using Lachain.UtilityTest; +using NUnit.Framework; + +namespace Lachain.CoreTest.IntegrationTests +{ + [TestFixture] + public class StorageSimulatorTest + { + private static readonly ILogger Logger = LoggerFactory.GetLoggerForClass(); + private static readonly ICrypto Crypto = CryptoProvider.GetCrypto(); + private static readonly ITransactionSigner Signer = new TransactionSigner(); + + private IBlockManager _blockManager = null!; + private ITransactionPool _transactionPool = null!; + private IStateManager _stateManager = null!; + private IStorageManager _storageManager = null!; + private IPrivateWallet _wallet = null!; + private IConfigManager _configManager = null!; + private INodeRetrieval _nodeRetrieval = null!; + private IContainer? _container; + + [SetUp] + public void Setup() + { + _container?.Dispose() ; + TestUtils.DeleteTestChainData(); + var containerBuilder = new SimpleInjectorContainerBuilder(new ConfigManager( + Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "config.json"), + new RunOptions() + )); + + containerBuilder.RegisterModule(); + containerBuilder.RegisterModule(); + containerBuilder.RegisterModule(); + containerBuilder.RegisterModule(); + containerBuilder.RegisterModule(); + _container = containerBuilder.Build(); + _blockManager = _container.Resolve(); + _stateManager = _container.Resolve(); + _storageManager = _container.Resolve(); + _wallet = _container.Resolve(); + _transactionPool = _container.Resolve(); + _configManager = _container.Resolve(); + _nodeRetrieval = _container.Resolve(); + + // set chainId from config + if (TransactionUtils.ChainId(false) == 0) + { + var chainId = _configManager.GetConfig("network")?.ChainId; + var newChainId = _configManager.GetConfig("network")?.NewChainId; + TransactionUtils.SetChainId((int)chainId!, (int)newChainId!); + HardforkHeights.SetHardforkHeights(_configManager.GetConfig("hardfork") ?? throw new InvalidOperationException()); + StakingContract.Initialize(_configManager.GetConfig("network")!); + } + } + + [TearDown] + public void Teardown() + { + _container?.Dispose(); + TestUtils.DeleteTestChainData(); + } + + [Test] + public void Test() + { + // execute some blocks + _blockManager.TryBuildGenesisBlock(); + var topUpReceipts = new List(); + var randomReceipts = new List(); + var txCount = 50; + + var coverTxFeeAmount = Money.Parse("10.0"); + for (var i = 0; i < txCount; i++) + { + var tx = TestUtils.GetRandomTransaction(HardforkHeights.IsHardfork_9Active(2)); + randomReceipts.Add(tx); + topUpReceipts.Add(TopUpBalanceTx(tx.Transaction.From, + (tx.Transaction.Value.ToMoney() + coverTxFeeAmount).ToUInt256(), i, + HardforkHeights.IsHardfork_9Active(1))); + } + + ExecuteTxesBlocks(topUpReceipts); + ExecuteTxesBlocks(randomReceipts); + var addresses = new HashSet(); + foreach (var tx in topUpReceipts) + { + addresses.Add(tx.Transaction.From); + addresses.Add(tx.Transaction.To); + } + foreach (var tx in randomReceipts) + { + addresses.Add(tx.Transaction.From); + addresses.Add(tx.Transaction.To); + } + var addressBalance = new Dictionary(); + foreach (var address in addresses) + { + var balance = _stateManager.LastApprovedSnapshot.Balances.GetBalance(address); + Assert.That(addressBalance.TryAdd(address, balance)); + } + var stateHash = _stateManager.LastApprovedSnapshot.StateHash; + var snapshots = _stateManager.LastApprovedSnapshot.GetAllSnapshot(); + var nodeVersions = new Dictionary(); + var nodes = new Dictionary(); + foreach (var snapshot in snapshots) + { + var version = snapshot.Version; + var node = _nodeRetrieval.TryGetNode(version); + Assert.That(nodeVersions.TryAdd(snapshot.RepositoryId, version)); + Assert.That(nodes.TryAdd(snapshot.RepositoryId, node)); + } + + // run state simulator, it should not commit and should not change state + // running state simulator should not affect _stateManager.LastApprovedSnapshot + + IStateManager stateSimulator = new StateSimulator(_storageManager); + // it should have all latest states + DiffSimulation(stateSimulator.LastApprovedSnapshot, true, stateHash, nodeVersions, nodes, addresses, addressBalance); + + // update balance of all of them + stateSimulator.SafeContext(() => + { + var newSnapshot = stateSimulator.NewSnapshot(); + SimulateState(newSnapshot, addresses, addressBalance); + DiffSimulation(newSnapshot, false, stateHash, nodeVersions, nodes, addresses, addressBalance); + }); + + DiffSimulation(stateSimulator.LastApprovedSnapshot, true, stateHash, nodeVersions, nodes, addresses, addressBalance); + var newSnapshot = stateSimulator.NewSnapshot(); + SimulateState(newSnapshot, addresses, addressBalance); + stateSimulator.Approve(); + DiffSimulation(stateSimulator.LastApprovedSnapshot, false, stateHash, nodeVersions, nodes, addresses, addressBalance); + stateSimulator = new StateSimulator(_storageManager); + DiffSimulation(stateSimulator.LastApprovedSnapshot, true, stateHash, nodeVersions, nodes, addresses, addressBalance); + DiffSimulation(_stateManager.LastApprovedSnapshot, true, stateHash, nodeVersions, nodes, addresses, addressBalance); + } + + private void DiffSimulation( + IBlockchainSnapshot currentSnapshot, bool match, UInt256 stateHash, + Dictionary nodeVersions, + Dictionary nodes, + HashSet addresses, + Dictionary addressBalance + ) + { + var newStateHash = currentSnapshot.StateHash; + Assert.AreEqual(match, stateHash.Equals(newStateHash)); + var snapshots = currentSnapshot.GetAllSnapshot(); + var matched = 0; + var notMatched = 0; + foreach (var snapshot in snapshots) + { + var version = snapshot.Version; + var node = _nodeRetrieval.TryGetNode(version); + Assert.That(nodeVersions.TryGetValue(snapshot.RepositoryId, out var realVersion)); + if (realVersion == version) matched++; + else notMatched++; + Assert.That(nodes.TryGetValue(snapshot.RepositoryId, out var realNode)); + if (match) Assert.AreEqual(realNode, node); + else + { + if (realVersion != version) Assert.AreNotEqual(realNode, node); + else Assert.AreEqual(realNode, node); + } + } + if (match) + { + Assert.AreEqual(snapshots.Length, matched); + } + else Assert.That(notMatched > 0); + + foreach (var address in addresses) + { + var balance = currentSnapshot.Balances.GetBalance(address); + Assert.That(addressBalance.TryGetValue(address, out var realBalance)); + Assert.AreEqual(match, balance.Equals(realBalance!)); + } + } + + private void SimulateState( + IBlockchainSnapshot snapshot, HashSetaddresses, Dictionary addressBalance + ) + { + var masterAddress = new EcdsaKeyPair("0xd95d6db65f3e2223703c5d8e205d98e3e6b470f067b0f94f6c6bf73d4301ce48" + .HexToBytes().ToPrivateKey()).PublicKey.GetAddress(); + + var balanceUpdate = Money.Parse("0.000000001"); + var oldBalance = snapshot.Balances.GetBalance(masterAddress); + foreach (var address in addresses) + { + if (!address.Equals(masterAddress)) + { + snapshot.Balances.TransferBalance(masterAddress, address, balanceUpdate, new TransactionReceipt(), true, true); + oldBalance -= balanceUpdate; + } + } + + foreach (var address in addresses) + { + var balance = snapshot.Balances.GetBalance(address); + if (address.Equals(masterAddress)) + { + Assert.AreEqual(oldBalance, balance); + } + else + { + Assert.That(addressBalance.TryGetValue(address, out var realBalance)); + Assert.AreEqual(realBalance! + balanceUpdate, balance); + } + } + } + + public void ExecuteTxesBlocks(List txes) + { + txes = txes.OrderBy(x => x, new ReceiptComparer()).ToList(); + foreach (var tx in txes) + { + _transactionPool.Add(tx); + } + var takenTxes = _transactionPool.Peek(txes.Count, txes.Count, _blockManager.GetHeight() + 1); + var block = BuildNextBlock(takenTxes.ToArray()); + var result = ExecuteBlock(block, takenTxes.ToArray()); + Assert.AreEqual(result, OperatingError.Ok); + var executedBlock = _stateManager.LastApprovedSnapshot.Blocks.GetBlockByHeight(block.Header.Index); + Assert.AreEqual(executedBlock!.TransactionHashes.Count, takenTxes.Count); + + // check if the txes are executed properly + foreach (var tx in takenTxes) + { + var executedTx = _stateManager.LastApprovedSnapshot.Transactions.GetTransactionByHash(tx.Hash); + Assert.AreNotEqual(null, executedTx, $"Transaction {tx.Hash.ToHex()} not found"); + Assert.AreEqual(TransactionStatus.Executed, executedTx!.Status, + "Transaction {tx.Hash.ToHex()} was not executed properly"); + } + } + + private Block BuildNextBlock(TransactionReceipt[]? receipts = null) + { + receipts ??= new TransactionReceipt[] { }; + + var merkleRoot = UInt256Utils.Zero; + + if (receipts.Any()) + merkleRoot = MerkleTree.ComputeRoot(receipts.Select(tx => tx.Hash).ToArray()) ?? + throw new InvalidOperationException(); + + var predecessor = + _stateManager.LastApprovedSnapshot.Blocks.GetBlockByHeight(_stateManager.LastApprovedSnapshot.Blocks + .GetTotalBlockHeight()); + var (header, multisig) = + BuildHeaderAndMultisig(merkleRoot, predecessor, _stateManager.LastApprovedSnapshot.StateHash); + + return new Block + { + Header = header, + Hash = header.Keccak(), + Multisig = multisig, + TransactionHashes = {receipts.Select(tx => tx.Hash)}, + }; + } + + private (BlockHeader, MultiSig) BuildHeaderAndMultisig(UInt256 merkleRoot, Block? predecessor, + UInt256 stateHash) + { + var blockIndex = predecessor!.Header.Index + 1; + var header = new BlockHeader + { + Index = blockIndex, + PrevBlockHash = predecessor!.Hash, + MerkleRoot = merkleRoot, + StateHash = stateHash, + Nonce = blockIndex + }; + + var keyPair = _wallet.EcdsaKeyPair; + + var headerSignature = Crypto.SignHashed( + header.Keccak().ToBytes(), + keyPair.PrivateKey.Encode(), HardforkHeights.IsHardfork_9Active(blockIndex) + ).ToSignature(HardforkHeights.IsHardfork_9Active(blockIndex)); + + var multisig = new MultiSig + { + Quorum = 1, + Validators = {_wallet.EcdsaKeyPair.PublicKey}, + Signatures = + { + new MultiSig.Types.SignatureByValidator + { + Key = _wallet.EcdsaKeyPair.PublicKey, + Value = headerSignature, + } + } + }; + return (header, multisig); + } + + private OperatingError ExecuteBlock(Block block, TransactionReceipt[]? receipts = null) + { + receipts ??= new TransactionReceipt[] { }; + + var (_, _, stateHash, _) = _blockManager.Emulate(block, receipts); + + var predecessor = + _stateManager.LastApprovedSnapshot.Blocks.GetBlockByHeight(_stateManager.LastApprovedSnapshot.Blocks + .GetTotalBlockHeight()); + var (header, multisig) = BuildHeaderAndMultisig(block.Header.MerkleRoot, predecessor, stateHash); + + block.Header = header; + block.Multisig = multisig; + block.Hash = header.Keccak(); + + var status = _blockManager.Execute(block, receipts, true, true); + Console.WriteLine($"Executed block: {block.Header.Index}"); + return status; + } + + private TransactionReceipt TopUpBalanceTx(UInt160 to, UInt256 value, int nonceInc, bool useNewChainId) + { + var keyPair = new EcdsaKeyPair("0xd95d6db65f3e2223703c5d8e205d98e3e6b470f067b0f94f6c6bf73d4301ce48" + .HexToBytes().ToPrivateKey()); + var tx = new Transaction + { + To = to, + From = keyPair.PublicKey.GetAddress(), + GasPrice = (ulong) Money.Parse("0.0000001").ToWei(), + GasLimit = 4_000_000, + Nonce = _transactionPool.GetNextNonceForAddress(keyPair.PublicKey.GetAddress()) + + (ulong) nonceInc, + Value = value + }; + return Signer.Sign(tx, keyPair, useNewChainId); + } + } +} \ No newline at end of file diff --git a/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs b/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs index f49cec1a8..f0e2519c9 100644 --- a/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs +++ b/test/Lachain.CoreTest/RPC/HTTP/Web3/AccountServiceWeb3Test.cs @@ -1,36 +1,37 @@ using System; +using System.IO; using System.Linq; using System.Numerics; using System.Reflection; -using Lachain.Core.RPC.HTTP.Web3; -using Lachain.UtilityTest; -using NUnit.Framework; -using Lachain.Core.DI; -using Lachain.Storage.State; +using AustinHarris.JsonRpc; +using Lachain.Core.Blockchain.Error; +using Lachain.Core.Blockchain.Genesis; +using Lachain.Core.Blockchain.Hardfork; using Lachain.Core.Blockchain.Interface; +using Lachain.Core.Blockchain.Pool; using Lachain.Core.Blockchain.SystemContracts; -using Lachain.Core.Vault; +using Lachain.Core.DI; using Lachain.Core.DI.Modules; using Lachain.Core.DI.SimpleInjector; using Lachain.Core.CLI; -using System.IO; using Lachain.Core.Config; -using AustinHarris.JsonRpc; -using Lachain.Storage.Repositories; -using Lachain.Utility; -using Lachain.Utility.Utils; -using Lachain.Core.Blockchain.Error; -using Lachain.Core.Blockchain.Genesis; -using Lachain.Core.Blockchain.Hardfork; +using Lachain.Core.RPC.HTTP.Web3; +using Lachain.Core.Vault; using Lachain.Crypto; -using Lachain.Proto; +using Lachain.Crypto.ECDSA; using Lachain.Crypto.Misc; -using Lachain.Core.Blockchain.Pool; using Lachain.Networking; -using Nethereum.Signer; +using Lachain.Proto; +using Lachain.Storage; +using Lachain.Storage.Repositories; +using Lachain.Storage.State; +using Lachain.Utility; using Lachain.Utility.Serialization; +using Lachain.Utility.Utils; +using Lachain.UtilityTest; +using Nethereum.Signer; +using NUnit.Framework; using Transaction = Lachain.Proto.Transaction; -using Lachain.Crypto.ECDSA; namespace Lachain.CoreTest.RPC.HTTP.Web3 @@ -41,6 +42,7 @@ public class AccountServiceWeb3Test private IConfigManager _configManager = null!; private IContainer? _container; private IStateManager _stateManager = null!; + private IStorageManager _storageManaer = null!; private ISnapshotIndexRepository _snapshotIndexer = null!; private IContractRegisterer _contractRegisterer = null!; private IPrivateWallet _privateWallet = null!; @@ -76,6 +78,7 @@ public void Setup() _configManager = _container.Resolve(); _stateManager = _container.Resolve(); + _storageManaer = _container.Resolve(); _contractRegisterer = _container.Resolve(); _privateWallet = _container.Resolve(); _snapshotIndexer = _container.Resolve(); @@ -100,7 +103,7 @@ public void Setup() _apiService = new AccountServiceWeb3(_stateManager, _snapshotIndexer, _contractRegisterer, _systemContractReader, _transactionPool); - _transactionApiService = new TransactionServiceWeb3(_stateManager, _transactionManager, _transactionBuilder, _transactionSigner, + _transactionApiService = new TransactionServiceWeb3(_storageManaer, _stateManager, _transactionManager, _transactionBuilder, _transactionSigner, _transactionPool, _contractRegisterer, _privateWallet, _blockManager); _blockManager.TryBuildGenesisBlock(); diff --git a/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs b/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs index b1a4c1be8..f2632c0f1 100644 --- a/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs +++ b/test/Lachain.CoreTest/RPC/HTTP/Web3/Web3TransactionTests.cs @@ -1,10 +1,12 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using AustinHarris.JsonRpc; using Lachain.Core.Blockchain.Error; +using Lachain.Core.Blockchain.Hardfork; using Lachain.Core.Blockchain.Interface; using Lachain.Core.Blockchain.Pool; using Lachain.Core.Blockchain.SystemContracts; @@ -19,19 +21,18 @@ using Lachain.Core.Vault; using Lachain.Crypto; using Lachain.Crypto.ECDSA; +using Lachain.Crypto.Misc; +using Lachain.Networking; using Lachain.Proto; +using Lachain.Storage; using Lachain.Storage.State; +using Lachain.Utility; +using Lachain.Utility.Serialization; using Lachain.Utility.Utils; using Lachain.UtilityTest; using Nethereum.Signer; -using NUnit.Framework; -using Lachain.Crypto.Misc; -using Lachain.Utility; -using System.Collections.Generic; -using Lachain.Core.Blockchain.Hardfork; -using Lachain.Networking; using Newtonsoft.Json.Linq; -using Lachain.Utility.Serialization; +using NUnit.Framework; namespace Lachain.CoreTest.RPC.HTTP.Web3 { @@ -46,6 +47,7 @@ public class Web3TransactionTests private IContractRegisterer _contractRegisterer = null!; private IPrivateWallet _privateWallet = null!; private IConfigManager _configManager = null!; + private IStorageManager _storageManager = null!; private TransactionServiceWeb3 _apiService = null!; @@ -83,6 +85,7 @@ public void Setup() _container = containerBuilder.Build(); _stateManager = _container.Resolve(); + _storageManager = _container.Resolve(); _transactionManager = _container.Resolve(); _transactionBuilder = _container.Resolve(); _transactionSigner = _container.Resolve(); @@ -102,7 +105,7 @@ public void Setup() } ServiceBinder.BindService(); - _apiService = new TransactionServiceWeb3(_stateManager, _transactionManager, _transactionBuilder, _transactionSigner, + _apiService = new TransactionServiceWeb3(_storageManager, _stateManager, _transactionManager, _transactionBuilder, _transactionSigner, _transactionPool, _contractRegisterer, _privateWallet, _blockManager); From e838a3978fed0d12383e04132fc6a06d3fab2794 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 6 Jan 2023 20:58:39 +0600 Subject: [PATCH 18/20] updated test --- .../Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs b/test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs index ef3d85ce6..0e27df71f 100644 --- a/test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs +++ b/test/Lachain.CoreTest/IntegrationTests/StorageSimulatorTest.cs @@ -224,7 +224,9 @@ private void SimulateState( { if (!address.Equals(masterAddress)) { - snapshot.Balances.TransferBalance(masterAddress, address, balanceUpdate, new TransactionReceipt(), true, true); + Assert.That(snapshot.Balances.TransferBalance( + masterAddress, address, balanceUpdate, new TransactionReceipt(), true, true + )); oldBalance -= balanceUpdate; } } From c391498a664711d5f256b803d866c113166f9b05 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Sun, 8 Jan 2023 23:08:11 +0600 Subject: [PATCH 19/20] removed unnecessary logs --- .../Blockchain/SystemContracts/NativeTokenContract.cs | 9 --------- src/Lachain.Core/Blockchain/VM/ExternalHandler.cs | 4 ---- 2 files changed, 13 deletions(-) diff --git a/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs b/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs index ded9ea18c..ba4605e48 100644 --- a/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs +++ b/src/Lachain.Core/Blockchain/SystemContracts/NativeTokenContract.cs @@ -120,10 +120,6 @@ public ExecutionStatus Transfer(UInt160 recipient, UInt256 value, SystemContract { frame.UseGas(GasMetering.NativeTokenTransferCost); var from = _context.Sender ?? throw new InvalidOperationException(); - var balance = _context.Snapshot.Balances.GetBalance(from); - Logger.LogTrace( - $"Transfer: from: {from.ToHex()} to: {recipient.ToHex()}, value: {value.ToMoney().ToString()}, balance: {balance.ToString()}" - ); bool result; if (HardforkHeights.IsHardfork_15Active(_context.Receipt.Block)) { @@ -182,11 +178,6 @@ public ExecutionStatus TransferFrom( { frame.UseGas(GasMetering.NativeTokenTransferFromCost); var allowance = GetAllowance(from, Sender()).ToMoney(); - var balance = _context.Snapshot.Balances.GetBalance(from); - Logger.LogTrace( - $"TransferFrom: from: {from.ToHex()} to: {recipient.ToHex()}, value: {value.ToMoney().ToString()}, " - + $"balance: {balance.ToString()}, allowance: {allowance.ToString()}" - ); if (!SubAllowance(from, Sender(), value, frame)) return ExecutionStatus.ExecutionHalted; var result = _context.Snapshot.Balances.TransferAllowance(from, recipient, value.ToMoney(), allowance); diff --git a/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs b/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs index 1eb7ea0e7..7bb71a022 100644 --- a/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs +++ b/src/Lachain.Core/Blockchain/VM/ExternalHandler.cs @@ -1487,10 +1487,6 @@ private static bool TransferBalance( var receipt = frame.InvocationContext.Receipt; var snapshot = frame.InvocationContext.Snapshot; var height = snapshot.Blocks.GetTotalBlockHeight(); - var balance = snapshot.Balances.GetBalance(from); - Logger.LogTrace( - $"TransferBalance: from: {from.ToHex()}, to: {to.ToHex()}, value: {value.ToString()}, balance: {balance.ToString()}" - ); if (HardforkHeights.IsHardfork_15Active(height)) { var contract = snapshot.Contracts.GetContractByHash(from); From e6b96cb87de6084ec8ebe116525328fc1e10d570 Mon Sep 17 00:00:00 2001 From: tbssajal Date: Fri, 13 Jan 2023 14:45:36 +0600 Subject: [PATCH 20/20] updated hardfork15 heights --- src/Lachain.Core/Config/ConfigManager.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Lachain.Core/Config/ConfigManager.cs b/src/Lachain.Core/Config/ConfigManager.cs index 53b5620d0..c7039d3b6 100644 --- a/src/Lachain.Core/Config/ConfigManager.cs +++ b/src/Lachain.Core/Config/ConfigManager.cs @@ -532,9 +532,9 @@ private void _UpdateConfigToV18() throw new ApplicationException("No hardfork section in config"); hardforks.Hardfork_15 ??= network.NetworkName switch { - "mainnet" => 6212300, - "testnet" => 5928300, - "devnet" => 1651300, + "mainnet" => 7887120, + "testnet" => 7490462, + "devnet" => 7887120, _ => 0 }; _config["hardfork"] = JObject.FromObject(hardforks);