neo: Storage.Find duplicate values
The Neo.Storage.Find
SYSCALL returns duplicate results causing the invoker to be charged for unnecessary extra Neo.Iterator.Key
and Neo.Iterator.Next
calls.
Take this contract
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
namespace NeoContract1
{
public class Contract1 : SmartContract
{
public static void Main(int op)
{
if (op == 1)
{
Storage.Put(Storage.CurrentContext, "AA_1", "1");
Storage.Put(Storage.CurrentContext, "AA_2", "2");
Storage.Put(Storage.CurrentContext, "AA_3", "3");
} else if (op == 2)
{
Iterator<string, byte[]> si = Storage.Find(Storage.CurrentContext, "AA_");
notify_results(si);
}
else if (op == 3)
{
Storage.Get(Storage.CurrentContext, "AA_1");
Iterator<string, byte[]> si = Storage.Find(Storage.CurrentContext, "AA_");
notify_results(si);
}
}
private static void notify_results(Iterator<string, byte[]> si)
{
Runtime.Notify("Starting");
while (si.Next())
{
Runtime.Notify(si.Key);
}
Runtime.Notify("Done");
}
}
}
Invoke the contract once with the contract op
argument being 1
to persist the contents to the DB. Next invoke the contract with op
being 2
and 3
.
2
gives the expected:AA_1
,AA_2
,AA_3
,3
however gives:AA_1
,AA_2
,AA_3
,AA_1
,AA_1
The last 2 values should not be there. I believe this is a caching issue.
Take a secondary contract that allows us to call Contract 1 multiple times in a single DB snapshot
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using System;
using System.Numerics;
namespace NeoContract2
{
public class Contract2 : SmartContract
{
[Appcall("f4032cfb5505c05d935db8bd41b608005eca0b00")]
public static extern void OtherContract(int op);
public static void Main(int op)
{
if (op == 1)
{
OtherContract(2);
OtherContract(2);
}
else if (op == 2)
{
OtherContract(2);
OtherContract(3);
}
else
{
OtherContract(3);
OtherContract(2);
}
}
}
}
op
is1
is still correct and produces:AA_1
,AA_2
,AA_3
followed by anotherAA_1
,AA_2
,AA_3
op
is2
is wrong in the same way it was wrong when calling contract 1 directly. We first getAA_1
,AA_2
,AA_3
followed byAA_1
,AA_2
,AA_3
,AA_1
,AA_1
op
is3
is where it gets really interesting. Given the previous results you’d expect:AA_1
,AA_2
,AA_3
,AA_1
,AA_1
followed byAA_1
,AA_2
,AA_3
. Instead you now get 2 times the sequenceAA_1
,AA_2
,AA_3
,AA_1
,AA_1
Contract AVM files included in the zip file for easy deploy/reproducing contracts.zip
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 15 (15 by maintainers)
I should not report issues after an extra long day of debugging. Made a rookie mistake by looking at neo-python’s interpretation 😅
Ricarrrdo, @lock9, here is our flag! 🗡️
But all issues need to be tagged, it has been like this since the old days. We have 96 issues open, 95 have tags, why this one is different? I just didn’t use the “discussion” tag, because this doesn’t look like a discussion. This looks more like a “support request”, I agree that bug may not be the best tag, but we need to tag it.