Skip to content
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/neo/SmartContract/Manifest/ContractAbi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,14 @@ public JObject ToJson()
json["events"] = new JArray(Events.Select(u => u.ToJson()).ToArray());
return json;
}

internal ContractAbi ForVersion(uint version)
{
return new ContractAbi()
{
Events = Events.Where(u => u.AvailableFromVersion <= version).ToArray(),
Methods = Methods.Where(u => u.AvailableFromVersion <= version).ToArray()
};
}
}
}
5 changes: 5 additions & 0 deletions src/neo/SmartContract/Manifest/ContractEventDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public class ContractEventDescriptor : IInteroperable
/// </summary>
public ContractParameterDefinition[] Parameters { get; set; }

/// <summary>
/// When the Method start to be available
/// </summary>
public uint AvailableFromVersion { get; set; } = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to send the Attribute value to the ContractEventDescriptor in order to know it for filtering

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to update the states.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


public virtual void FromStackItem(StackItem stackItem)
{
Struct @struct = (Struct)stackItem;
Expand Down
14 changes: 14 additions & 0 deletions src/neo/SmartContract/Manifest/ContractManifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,20 @@ public StackItem ToStackItem(ReferenceCounter referenceCounter)
};
}

internal ContractManifest ForVersion(uint version)
{
return new ContractManifest()
{
Abi = Abi.ForVersion(version),
Extra = Extra?.Clone(),
Groups = Groups,
Name = Name,
Permissions = Permissions,
SupportedStandards = SupportedStandards,
Trusts = Trusts,
};
}

/// <summary>
/// Converts the manifest from a JSON object.
/// </summary>
Expand Down
12 changes: 10 additions & 2 deletions src/neo/SmartContract/Native/ContractManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public sealed class ContractManagement : NativeContract
private const byte Prefix_MinimumDeploymentFee = 20;
private const byte Prefix_NextAvailableId = 15;
private const byte Prefix_Contract = 8;
private const byte Prefix_NextVersion = 4;

internal ContractManagement()
{
Expand Down Expand Up @@ -104,16 +105,23 @@ internal override async ContractTask OnPersist(ApplicationEngine engine)
foreach (NativeContract contract in Contracts)
{
uint[] updates = engine.ProtocolSettings.NativeUpdateHistory[contract.Name];
if (updates.Length == 0 || updates[0] != engine.PersistingBlock.Index)
StorageKey versionKey = CreateStorageKey(Prefix_NextVersion).Add(contract.Hash);
StorageItem versionValue = engine.Snapshot.TryGet(versionKey);
uint version = versionValue == null ? 0 : (uint)(BigInteger)versionValue;
if (updates.Length <= version) continue;
if (updates[version] != engine.PersistingBlock.Index)
continue;
engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState
{
Id = contract.Id,
Nef = contract.Nef,
Hash = contract.Hash,
Manifest = contract.Manifest
UpdateCounter = (ushort)version,
Manifest = contract.Manifest.ForVersion(version) // Get versioned Abi
}));
engine.Snapshot.Add(versionKey, new StorageItem(new BigInteger(version + 1)));
await contract.Initialize(engine);
engine.SendNotification(Hash, version != 0 ? "Update" : "Deploy", new VM.Types.Array { contract.Hash.ToArray(), version });
}
}

Expand Down
1 change: 1 addition & 0 deletions src/neo/SmartContract/Native/ContractMethodAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ internal class ContractMethodAttribute : Attribute
public CallFlags RequiredCallFlags { get; init; }
public long CpuFee { get; init; }
public long StorageFee { get; init; }
public uint AvailableFromVersion { get; init; } = 0;
}
}
3 changes: 2 additions & 1 deletion src/neo/SmartContract/Native/ContractMethodMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public ContractMethodMetadata(MemberInfo member, ContractMethodAttribute attribu
Name = Name,
ReturnType = ToParameterType(Handler.ReturnType),
Parameters = Parameters.Select(p => new ContractParameterDefinition { Type = ToParameterType(p.Type), Name = p.Name }).ToArray(),
Safe = (attribute.RequiredCallFlags & ~CallFlags.ReadOnly) == 0
Safe = (attribute.RequiredCallFlags & ~CallFlags.ReadOnly) == 0,
AvailableFromVersion = attribute.AvailableFromVersion
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/neo/SmartContract/Native/LedgerContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ private Transaction GetTransactionForContract(ApplicationEngine engine, UInt256
return state.Transaction;
}

[ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)]
[ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates, AvailableFromVersion = 1)]
private VMState GetTransactionVMState(ApplicationEngine engine, UInt256 hash)
{
TransactionState state = GetTransactionState(engine.Snapshot, hash);
Expand Down