Skip to content

Commit

Permalink
add new APIs for NeoContract
Browse files Browse the repository at this point in the history
1. Add `Neo.Runtime.Serialize` and `Neo.Runtime.Deserialize`
1. Update dependency: Neo.VM v2.1.0
  • Loading branch information
Erik Zhang authored and erikzhang committed Feb 5, 2018
1 parent 06a900b commit f0cf5cc
Show file tree
Hide file tree
Showing 7 changed files with 510 additions and 227 deletions.
7 changes: 5 additions & 2 deletions neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Neo.Core;
using Neo.IO.Caching;
using Neo.VM;
using Neo.VM.Types;
using System.Numerics;
using System.Text;

Expand Down Expand Up @@ -223,8 +224,10 @@ private bool CheckStackSize(OpCode nextInstruction)
break;
case OpCode.UNPACK:
StackItem item = EvaluationStack.Peek();
if (!item.IsArray) return false;
size = item.GetArray().Count;
if (item is Array array)
size = array.Count;
else
return false;
break;
}
if (size == 0) return true;
Expand Down
12 changes: 12 additions & 0 deletions neo/SmartContract/StackItemType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Neo.SmartContract
{
internal enum StackItemType : byte
{
ByteArray = 0x00,
Boolean = 0x01,
Integer = 0x02,
InteropInterface = 0x40,
Array = 0x80,
Struct = 0x81,
}
}
117 changes: 69 additions & 48 deletions neo/SmartContract/StateMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Neo.Cryptography.ECC;
using Neo.IO.Caching;
using Neo.VM;
using Neo.VM.Types;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -148,22 +149,26 @@ private bool Asset_Create(ExecutionEngine engine)

private bool Asset_Renew(ExecutionEngine engine)
{
AssetState asset = engine.EvaluationStack.Pop().GetInterface<AssetState>();
if (asset == null) return false;
byte years = (byte)engine.EvaluationStack.Pop().GetBigInteger();
asset = assets.GetAndChange(asset.AssetId);
if (asset.Expiration < Blockchain.Default.Height + 1)
asset.Expiration = Blockchain.Default.Height + 1;
try
{
asset.Expiration = checked(asset.Expiration + years * 2000000u);
}
catch (OverflowException)
if (engine.EvaluationStack.Pop() is InteropInterface _interface)
{
asset.Expiration = uint.MaxValue;
AssetState asset = _interface.GetInterface<AssetState>();
if (asset == null) return false;
byte years = (byte)engine.EvaluationStack.Pop().GetBigInteger();
asset = assets.GetAndChange(asset.AssetId);
if (asset.Expiration < Blockchain.Default.Height + 1)
asset.Expiration = Blockchain.Default.Height + 1;
try
{
asset.Expiration = checked(asset.Expiration + years * 2000000u);
}
catch (OverflowException)
{
asset.Expiration = uint.MaxValue;
}
engine.EvaluationStack.Push(asset.Expiration);
return true;
}
engine.EvaluationStack.Push(asset.Expiration);
return true;
return false;
}

private bool Contract_Create(ExecutionEngine engine)
Expand Down Expand Up @@ -264,14 +269,18 @@ private bool Contract_Migrate(ExecutionEngine engine)

private bool Contract_GetStorageContext(ExecutionEngine engine)
{
ContractState contract = engine.EvaluationStack.Pop().GetInterface<ContractState>();
if (!contracts_created.TryGetValue(contract.ScriptHash, out UInt160 created)) return false;
if (!created.Equals(new UInt160(engine.CurrentContext.ScriptHash))) return false;
engine.EvaluationStack.Push(StackItem.FromInterface(new StorageContext
if (engine.EvaluationStack.Pop() is InteropInterface _interface)
{
ScriptHash = contract.ScriptHash
}));
return true;
ContractState contract = _interface.GetInterface<ContractState>();
if (!contracts_created.TryGetValue(contract.ScriptHash, out UInt160 created)) return false;
if (!created.Equals(new UInt160(engine.CurrentContext.ScriptHash))) return false;
engine.EvaluationStack.Push(StackItem.FromInterface(new StorageContext
{
ScriptHash = contract.ScriptHash
}));
return true;
}
return false;
}

private bool Contract_Destroy(ExecutionEngine engine)
Expand All @@ -288,44 +297,56 @@ private bool Contract_Destroy(ExecutionEngine engine)

protected override bool Storage_Get(ExecutionEngine engine)
{
StorageContext context = engine.EvaluationStack.Pop().GetInterface<StorageContext>();
if (!CheckStorageContext(context)) return false;
byte[] key = engine.EvaluationStack.Pop().GetByteArray();
StorageItem item = storages.TryGet(new StorageKey
if (engine.EvaluationStack.Pop() is InteropInterface _interface)
{
ScriptHash = context.ScriptHash,
Key = key
});
engine.EvaluationStack.Push(item?.Value ?? new byte[0]);
return true;
StorageContext context = _interface.GetInterface<StorageContext>();
if (!CheckStorageContext(context)) return false;
byte[] key = engine.EvaluationStack.Pop().GetByteArray();
StorageItem item = storages.TryGet(new StorageKey
{
ScriptHash = context.ScriptHash,
Key = key
});
engine.EvaluationStack.Push(item?.Value ?? new byte[0]);
return true;
}
return false;
}

private bool Storage_Put(ExecutionEngine engine)
{
StorageContext context = engine.EvaluationStack.Pop().GetInterface<StorageContext>();
if (!CheckStorageContext(context)) return false;
byte[] key = engine.EvaluationStack.Pop().GetByteArray();
if (key.Length > 1024) return false;
byte[] value = engine.EvaluationStack.Pop().GetByteArray();
storages.GetAndChange(new StorageKey
if (engine.EvaluationStack.Pop() is InteropInterface _interface)
{
ScriptHash = context.ScriptHash,
Key = key
}, () => new StorageItem()).Value = value;
return true;
StorageContext context = _interface.GetInterface<StorageContext>();
if (!CheckStorageContext(context)) return false;
byte[] key = engine.EvaluationStack.Pop().GetByteArray();
if (key.Length > 1024) return false;
byte[] value = engine.EvaluationStack.Pop().GetByteArray();
storages.GetAndChange(new StorageKey
{
ScriptHash = context.ScriptHash,
Key = key
}, () => new StorageItem()).Value = value;
return true;
}
return false;
}

private bool Storage_Delete(ExecutionEngine engine)
{
StorageContext context = engine.EvaluationStack.Pop().GetInterface<StorageContext>();
if (!CheckStorageContext(context)) return false;
byte[] key = engine.EvaluationStack.Pop().GetByteArray();
storages.Delete(new StorageKey
if (engine.EvaluationStack.Pop() is InteropInterface _interface)
{
ScriptHash = context.ScriptHash,
Key = key
});
return true;
StorageContext context = _interface.GetInterface<StorageContext>();
if (!CheckStorageContext(context)) return false;
byte[] key = engine.EvaluationStack.Pop().GetByteArray();
storages.Delete(new StorageKey
{
ScriptHash = context.ScriptHash,
Key = key
});
return true;
}
return false;
}
}
}
Loading

0 comments on commit f0cf5cc

Please sign in to comment.