Skip to content

Commit

Permalink
Automatically set Id for native contracts (#2210)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikzhang committed Jan 10, 2021
1 parent d0a4976 commit dfb56a2
Show file tree
Hide file tree
Showing 13 changed files with 31 additions and 43 deletions.
4 changes: 2 additions & 2 deletions src/neo/SmartContract/ApplicationEngine.Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ protected internal void CallContract(UInt160 contractHash, string method, CallFl
CallContractInternal(contract, md, callFlags, hasReturnValue, args);
}

protected internal void CallNativeContract(string name)
protected internal void CallNativeContract(int id)
{
NativeContract contract = NativeContract.GetContract(name);
NativeContract contract = NativeContract.GetContract(id);
if (contract is null || contract.ActiveBlockIndex > Snapshot.Height)
throw new InvalidOperationException();
contract.Invoke(this);
Expand Down
2 changes: 0 additions & 2 deletions src/neo/SmartContract/Native/ContractManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ namespace Neo.SmartContract.Native
{
public sealed class ContractManagement : NativeContract
{
public override int Id => 0;

private const byte Prefix_MinimumDeploymentFee = 20;
private const byte Prefix_NextAvailableId = 15;
private const byte Prefix_Contract = 8;
Expand Down
1 change: 0 additions & 1 deletion src/neo/SmartContract/Native/GasToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ namespace Neo.SmartContract.Native
{
public sealed class GasToken : FungibleToken<AccountState>
{
public override int Id => -2;
public override string Symbol => "GAS";
public override byte Decimals => 8;

Expand Down
1 change: 0 additions & 1 deletion src/neo/SmartContract/Native/NameService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ namespace Neo.SmartContract.Native
{
public sealed class NameService : NonfungibleToken<NameService.NameState>
{
public override int Id => -6;
public override string Symbol => "NNS";

private const byte Prefix_Roots = 10;
Expand Down
18 changes: 11 additions & 7 deletions src/neo/SmartContract/Native/NativeContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,37 @@ namespace Neo.SmartContract.Native
public abstract class NativeContract
{
private static readonly List<NativeContract> contractsList = new List<NativeContract>();
private static readonly Dictionary<string, NativeContract> contractsNameDictionary = new Dictionary<string, NativeContract>();
private static readonly Dictionary<int, NativeContract> contractsIdDictionary = new Dictionary<int, NativeContract>();
private static readonly Dictionary<UInt160, NativeContract> contractsHashDictionary = new Dictionary<UInt160, NativeContract>();
private readonly Dictionary<string, ContractMethodMetadata> methods = new Dictionary<string, ContractMethodMetadata>();
private static int id_counter = 0;

public static IReadOnlyCollection<NativeContract> Contracts { get; } = contractsList;
#region Named Native Contracts
public static ContractManagement ContractManagement { get; } = new ContractManagement();
public static NeoToken NEO { get; } = new NeoToken();
public static GasToken GAS { get; } = new GasToken();
public static PolicyContract Policy { get; } = new PolicyContract();
public static RoleManagement RoleManagement { get; } = new RoleManagement();
public static OracleContract Oracle { get; } = new OracleContract();
public static NameService NameService { get; } = new NameService();
#endregion

public static IReadOnlyCollection<NativeContract> Contracts { get; } = contractsList;
public string Name => GetType().Name;
public NefFile Nef { get; }
public byte[] Script => Nef.Script;
public UInt160 Hash { get; }
public abstract int Id { get; }
public int Id { get; }
public ContractManifest Manifest { get; }
public uint ActiveBlockIndex { get; }

protected NativeContract()
{
this.Id = --id_counter;
byte[] script;
using (ScriptBuilder sb = new ScriptBuilder())
{
sb.EmitPush(Name);
sb.EmitPush(Id);
sb.EmitSysCall(ApplicationEngine.System_Contract_CallNative);
script = sb.ToArray();
}
Expand Down Expand Up @@ -85,7 +89,7 @@ protected NativeContract()
if (ProtocolSettings.Default.NativeActivations.TryGetValue(Name, out uint activationIndex))
this.ActiveBlockIndex = activationIndex;
contractsList.Add(this);
contractsNameDictionary.Add(Name, this);
contractsIdDictionary.Add(Id, this);
contractsHashDictionary.Add(Hash, this);
}

Expand All @@ -106,9 +110,9 @@ public static NativeContract GetContract(UInt160 hash)
return contract;
}

public static NativeContract GetContract(string name)
public static NativeContract GetContract(int id)
{
contractsNameDictionary.TryGetValue(name, out var contract);
contractsIdDictionary.TryGetValue(id, out var contract);
return contract;
}

Expand Down
1 change: 0 additions & 1 deletion src/neo/SmartContract/Native/NeoToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ namespace Neo.SmartContract.Native
{
public sealed class NeoToken : FungibleToken<NeoToken.NeoAccountState>
{
public override int Id => -1;
public override string Symbol => "NEO";
public override byte Decimals => 0;
public BigInteger TotalAmount { get; }
Expand Down
2 changes: 0 additions & 2 deletions src/neo/SmartContract/Native/OracleContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ public sealed class OracleContract : NativeContract

private const long OracleRequestPrice = 0_50000000;

public override int Id => -5;

internal OracleContract()
{
var events = new List<ContractEventDescriptor>(Manifest.Abi.Events)
Expand Down
2 changes: 0 additions & 2 deletions src/neo/SmartContract/Native/PolicyContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ namespace Neo.SmartContract.Native
{
public sealed class PolicyContract : NativeContract
{
public override int Id => -3;

public const uint DefaultExecFeeFactor = 30;
public const uint DefaultStoragePrice = 100000;
private const uint MaxExecFeeFactor = 1000;
Expand Down
2 changes: 0 additions & 2 deletions src/neo/SmartContract/Native/RoleManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ namespace Neo.SmartContract.Native
{
public sealed class RoleManagement : NativeContract
{
public override int Id => -4;

internal RoleManagement()
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ public StorageKey CreateStorageKey(byte prefix, byte[] key = null)

public class TestNep17Token : FungibleToken<NeoToken.NeoAccountState>
{
public override int Id => 0x10000005;
public override string Symbol => throw new NotImplementedException();
public override byte Decimals => 8;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ public void TestInitialize()

private class DummyNative : NativeContract
{
public override int Id => 1;

[ContractMethod(0, CallFlags.None)]
public void NetTypes(
bool p1, sbyte p2, byte p3, short p4, ushort p5, int p6, uint p7, long p8, ulong p9, BigInteger p10,
Expand Down Expand Up @@ -90,7 +88,7 @@ public void TestToParameter()
[TestMethod]
public void TestGetContract()
{
Assert.IsTrue(NativeContract.NEO == NativeContract.GetContract(NativeContract.NEO.Name));
Assert.IsTrue(NativeContract.NEO == NativeContract.GetContract(NativeContract.NEO.Id));
Assert.IsTrue(NativeContract.NEO == NativeContract.GetContract(NativeContract.NEO.Hash));
}

Expand Down Expand Up @@ -136,8 +134,6 @@ public void TestTestCall()

public class TestNativeContract : NativeContract
{
public override int Id => 0x10000006;

[ContractMethod(0, CallFlags.None)]
public string HelloWorld => "hello world";

Expand Down
32 changes: 16 additions & 16 deletions tests/neo.UnitTests/SmartContract/Native/UT_NeoToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ public void TestCalculateBonus()
Balance = 100,
VoteTo = Blockchain.StandbyCommittee[0]
}));
snapshot.Storages.Add(new KeyBuilder(-1, 23).Add(Blockchain.StandbyCommittee[0]).AddBigEndian(uint.MaxValue - 50), new StorageItem() { Value = new BigInteger(50 * 10000L).ToByteArray() });
snapshot.Storages.Add(new KeyBuilder(-2, 23).Add(Blockchain.StandbyCommittee[0]).AddBigEndian(uint.MaxValue - 50), new StorageItem() { Value = new BigInteger(50 * 10000L).ToByteArray() });
NativeContract.NEO.UnclaimedGas(snapshot, UInt160.Zero, 100).Should().Be(new BigInteger(50 * 100));
snapshot.Storages.Delete(key);
}
Expand Down Expand Up @@ -569,36 +569,36 @@ public void TestCheckCandidate()
var point = committee[0].EncodePoint(true);

// Prepare Prefix_VoterRewardPerCommittee
var storageKey = new KeyBuilder(-1, 23).Add(committee[0]).AddBigEndian(20);
var storageKey = new KeyBuilder(-2, 23).Add(committee[0]).AddBigEndian(20);
snapshot.Storages.Add(storageKey, new StorageItem(new BigInteger(1000)));

// Prepare Candidate
storageKey = new KeyBuilder(-1, 33).Add(committee[0]);
storageKey = new KeyBuilder(-2, 33).Add(committee[0]);
snapshot.Storages.Add(storageKey, new StorageItem(new CandidateState { Registered = true, Votes = BigInteger.One }));

storageKey = new KeyBuilder(-1, 23).Add(committee[0]);
storageKey = new KeyBuilder(-2, 23).Add(committee[0]);
snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1);

// Pre-persist
var persistingBlock = new Block { Index = 21, Transactions = Array.Empty<Transaction>() };
var persistingBlock = new Block { Index = 21, ConsensusData = new ConsensusData(), Transactions = Array.Empty<Transaction>() };
Check_OnPersist(snapshot, persistingBlock);

// Clear votes
storageKey = new KeyBuilder(-1, 33).Add(committee[0]);
storageKey = new KeyBuilder(-2, 33).Add(committee[0]);
snapshot.Storages.GetAndChange(storageKey).GetInteroperable<CandidateState>().Votes = BigInteger.Zero;

// Unregister candidate, remove
var ret = Check_UnregisterCandidate(snapshot, point, persistingBlock);
ret.State.Should().BeTrue();
ret.Result.Should().BeTrue();

storageKey = new KeyBuilder(-1, 23).Add(committee[0]);
storageKey = new KeyBuilder(-2, 23).Add(committee[0]);
snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(0);

// Post-persist
Check_PostPersist(snapshot, persistingBlock).Should().BeTrue();

storageKey = new KeyBuilder(-1, 23).Add(committee[0]);
storageKey = new KeyBuilder(-2, 23).Add(committee[0]);
snapshot.Storages.Find(storageKey.ToArray()).ToArray().Length.Should().Be(1);
}

Expand Down Expand Up @@ -713,16 +713,16 @@ public void TestClaimGas()
for (var i = 0; i < ProtocolSettings.Default.CommitteeMembersCount; i++)
{
ECPoint member = standbyCommittee[i];
snapshot.Storages.Add(new KeyBuilder(-1, 33).Add(member), new StorageItem(new CandidateState()
snapshot.Storages.Add(new KeyBuilder(-2, 33).Add(member), new StorageItem(new CandidateState()
{
Registered = true,
Votes = 200 * 10000
}));
cachedCommittee.Add((member, 200 * 10000));
}
snapshot.Storages[new KeyBuilder(-1, 14)].Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096);
snapshot.Storages[new KeyBuilder(-2, 14)].Value = BinarySerializer.Serialize(cachedCommittee.ToStackItem(null), 4096);

var item = snapshot.Storages.GetAndChange(new KeyBuilder(-1, 1), () => new StorageItem());
var item = snapshot.Storages.GetAndChange(new KeyBuilder(-2, 1), () => new StorageItem());
item.Value = ((BigInteger)2100 * 10000L).ToByteArray();

var persistingBlock = new Block { Index = 0, Transactions = Array.Empty<Transaction>() };
Expand All @@ -733,10 +733,10 @@ public void TestClaimGas()
var accountB = committee[ProtocolSettings.Default.CommitteeMembersCount - 1];
NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(accountA).ScriptHash).Should().Be(0);

StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountA).AddBigEndian(1));
StorageItem storageItem = snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(accountA).AddBigEndian(1));
new BigInteger(storageItem.Value).Should().Be(30000000000);

snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull();
snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(accountB).AddBigEndian(uint.MaxValue - 1)).Should().BeNull();

// Next block

Expand All @@ -745,7 +745,7 @@ public void TestClaimGas()

NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[1]).ScriptHash).Should().Be(0);

storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[1]).AddBigEndian(1));
storageItem = snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(committee[1]).AddBigEndian(1));
new BigInteger(storageItem.Value).Should().Be(30000000000);

// Next block
Expand All @@ -756,13 +756,13 @@ public void TestClaimGas()
accountA = Blockchain.StandbyCommittee.OrderBy(p => p).ToArray()[2];
NativeContract.NEO.BalanceOf(snapshot, Contract.CreateSignatureContract(committee[2]).ScriptHash).Should().Be(0);

storageItem = snapshot.Storages.TryGet(new KeyBuilder(-1, 23).Add(committee[2]).AddBigEndian(22));
storageItem = snapshot.Storages.TryGet(new KeyBuilder(-2, 23).Add(committee[2]).AddBigEndian(22));
new BigInteger(storageItem.Value).Should().Be(30000000000 * 2);

// Claim GAS

var account = Contract.CreateSignatureContract(committee[2]).ScriptHash;
snapshot.Storages.Add(new KeyBuilder(-1, 20).Add(account), new StorageItem(new NeoAccountState
snapshot.Storages.Add(new KeyBuilder(-2, 20).Add(account), new StorageItem(new NeoAccountState
{
BalanceHeight = 3,
Balance = 200 * 10000 - 2 * 100,
Expand Down
2 changes: 1 addition & 1 deletion tests/neo.UnitTests/VM/UT_Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public void TestMakeScript()
{
byte[] testScript = NativeContract.GAS.Hash.MakeScript("balanceOf", UInt160.Zero);

Assert.AreEqual("0c14000000000000000000000000000000000000000011c01f0c0962616c616e63654f660c141717ddafdd757eec365865b963473beb617f9a1441627d5b52",
Assert.AreEqual("0c14000000000000000000000000000000000000000011c01f0c0962616c616e63654f660c14a282435d0ee334fecaac7f5fde46f623f24cc09a41627d5b52",
testScript.ToHexString());
}

Expand Down

0 comments on commit dfb56a2

Please sign in to comment.