Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Plugin for UTXO tracking by account. #52

Merged
merged 18 commits into from
Mar 14, 2019

Conversation

jsolman
Copy link
Contributor

@jsolman jsolman commented Mar 11, 2019

This plugin facilitates sending NEO or GAS for arbitrary addresses by providing an RPC method getunspents for retrieving the unspent UTXOs. The unspent UTXOs are stored indexed by account script hash in an additional LevelDB database whose path is configurable in the plugin settings. This plugin was migrated from my initial PR here: neo-project/neo/pull/569

The format of the response data is compatible with the format returned from the neoscan v1 API get_balance` call.

@jsolman jsolman requested a review from erikzhang March 11, 2019 20:11
@jsolman
Copy link
Contributor Author

jsolman commented Mar 11, 2019

I'll be testing this by re-syncing MainNet from the latest chain file and will report here with the results from my testing.

@vncoelho
Copy link
Member

Building and testing it now.

@vncoelho
Copy link
Member

vncoelho commented Mar 11, 2019

I got this error but need double check, maybe it is my configuration.

[ERROR][03/11/2019 20:24:58][Thread 0004][akka://NeoSystem/user/$a] Error while creating actor instance of type Neo.Ledger.Blockchain with 2 args: (Neo.NeoSystem,Neo.Persistence.LevelDB.LevelDBStore)
Cause: [akka://NeoSystem/user/$a#360886005]: Akka.Actor.ActorInitializationException: Exception during creation ---> System.TypeLoadException: Error while creating actor instance of type Neo.Ledger.Blockchain with 2 args: (Neo.NeoSystem,Neo.Persistence.LevelDB.LevelDBStore) ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.) ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Neo.Plugins.RpcSystemAssetPlugin.OnCommit(Snapshot snapshot)
   at Neo.Ledger.Blockchain.Persist(Block block)
   --- End of inner exception stack trace ---
   at Neo.Ledger.Blockchain.Persist(Block block)
   at Neo.Ledger.Blockchain..ctor(NeoSystem system, Store store)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at Akka.Actor.Props.ActivatorProducer.Produce()
   at Akka.Actor.Props.NewActor()
   --- End of inner exception stack trace ---
   at Akka.Actor.Props.NewActor()
   at Akka.Actor.ActorCell.CreateNewActorInstance()
   at Akka.Actor.ActorCell.<>c__DisplayClass109_0.<NewActor>b__0()
   at Akka.Actor.ActorCell.UseThreadContext(Action action)
   at Akka.Actor.ActorCell.NewActor()
   at Akka.Actor.ActorCell.Create(Exception failure)
   --- End of inner exception stack trace ---
   at Akka.Actor.ActorCell.Create(Exception failure)
   at Akka.Actor.ActorCell.SysMsgInvokeAll(EarliestFirstSystemMessageList messages, Int32 currentState)

EDIT: I just tested removing the plugin .ddl and error disappeared.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 11, 2019

@vncoelho Maybe it is trying to persist the genesis block before the plugin is loaded. I'll check into it.

Actually, must be something else.

Copy link
Member

@vncoelho vncoelho left a comment

Choose a reason for hiding this comment

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

Maybe the folder can be just RpcSystemAsset.

@vncoelho
Copy link
Member

Sorry for not checking it in detail, @jsolman. I will also try to check it more tomorrow.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 11, 2019

Maybe the folder can be just RpcSystemAsset.

Maybe RpcSystemAssetTracker

Copy link
Member

@vncoelho vncoelho left a comment

Choose a reason for hiding this comment

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

[ERROR][03/11/2019 20:42:34][Thread 0006][akka://NeoSystem/user/$a] Error while creating actor instance of type Neo.Ledger.Blockchain with 2 args: (Neo.NeoSystem,Neo.Persistence.LevelDB.LevelDBStore)
Cause: [akka://NeoSystem/user/$a#123821120]: Akka.Actor.ActorInitializationException: Exception during creation ---> System.TypeLoadException: Error while creating actor instance of type Neo.Ledger.Blockchain with 2 args: (Neo.NeoSystem,Neo.Persistence.LevelDB.LevelDBStore) ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at Neo.Ledger.Blockchain.Persist(Block block)
   at Neo.Ledger.Blockchain..ctor(NeoSystem system, Store store)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at Akka.Actor.Props.ActivatorProducer.Produce()
   at Akka.Actor.Props.NewActor()
   --- End of inner exception stack trace ---
   at Akka.Actor.Props.NewActor()
   at Akka.Actor.ActorCell.CreateNewActorInstance()
   at Akka.Actor.ActorCell.<>c__DisplayClass109_0.<NewActor>b__0()
   at Akka.Actor.ActorCell.UseThreadContext(Action action)
   at Akka.Actor.ActorCell.NewActor()
   at Akka.Actor.ActorCell.Create(Exception failure)
   --- End of inner exception stack trace ---
   at Akka.Actor.ActorCell.Create(Exception failure)
   at Akka.Actor.ActorCell.SysMsgInvokeAll(EarliestFirstSystemMessageList messages, Int32 currentState)

This error is a little different, maybe this can help to track.

@vncoelho
Copy link
Member

@jsolman, it works for scripthash, right? Not base58?

@vncoelho
Copy link
Member

[ERROR][03/11/2019 21:16:49][Thread 0003][akka://NeoSystem/user/$a] Error while creating actor instance of type Neo.Ledger.Blockchain with 2 args: (Neo.NeoSystem,Neo.Persistence.LevelDB.LevelDBStore)
Cause: [akka://NeoSystem/user/$a#1123270816]: Akka.Actor.ActorInitializationException: Exception during creation ---> System.TypeLoadException: Error while creating actor instance of type Neo.Ledger.Blockchain with 2 args: (Neo.NeoSystem,Neo.Persistence.LevelDB.LevelDBStore) ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Neo.Plugins.RpcSystemAssetTrackerPlugin.ResetBatch()
   at Neo.Plugins.RpcSystemAssetTrackerPlugin.OnPersist(Snapshot snapshot, IReadOnlyList`1 applicationExecutedList)
   at Neo.Ledger.Blockchain.Persist(Block block)
   at Neo.Ledger.Blockchain..ctor(NeoSystem system, Store store)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at Akka.Actor.Props.ActivatorProducer.Produce()
   at Akka.Actor.Props.NewActor()
   --- End of inner exception stack trace ---
   at Akka.Actor.Props.NewActor()
   at Akka.Actor.ActorCell.CreateNewActorInstance()
   at Akka.Actor.ActorCell.<>c__DisplayClass109_0.<NewActor>b__0()
   at Akka.Actor.ActorCell.UseThreadContext(Action action)
   at Akka.Actor.ActorCell.NewActor()
   at Akka.Actor.ActorCell.Create(Exception failure)
   --- End of inner exception stack trace ---
   at Akka.Actor.ActorCell.Create(Exception failure)
   at Akka.Actor.ActorCell.SysMsgInvokeAll(EarliestFirstSystemMessageList messages, Int32 currentState)

This log is more precise now, @jsolman

@jsolman
Copy link
Contributor Author

jsolman commented Mar 11, 2019

@jsolman, it works for scripthash, right? Not base58?

I'll make it work for both.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 11, 2019

I need to change the plugins so they can override a method that will be called when all plugins have finished loading (ImportBlocks needs to start its work after all plugins are loaded for example). Also, the genesis block needs to not be persisted until plugins are loaded.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 11, 2019

Blocks are importing now and I'll report back on how testing goes.
This change is required: neo-project/neo/pull/633

@jsolman
Copy link
Contributor Author

jsolman commented Mar 12, 2019

Testing after syncing with MainNet looks good. Keep in mind that to use this you need:

  1. To be using Neo 2.10.1 (currently master at or above commit neo-project/neo@432a3f6)
  2. The updated ImportBlocks plugin: Import blocks after plugins are loaded. #53

Also, to be safe currently, do not stop the import blocks process when importing from chain file by using the exit command or control+c. I am going to improve shutdown to capture control+c and shutdown cleanly, but currently exit will hang while importing blocks, and interrupting could possibly stop after a block had been committed to the main LevelDB database and before the UTXOs are committed to this LevelDB database, leaving them in an inconsistent state.

As an improvement, I could likely have it persist the block number in LevelDB when this plugin commits so that it can check if it didn't persist the latest block on start-up and handle it that way.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 13, 2019

I have not done any testing yet after adding the last commit that adds the RPC method to get the claimable spent transactions. I will test it tomorrow and also likely add a method for getting the total unclaimed gas available for an address to fill the last gap.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 13, 2019

The API for getting all the claimable transactions is working as expected from my testing with MainNet. Now all that remains is implementing an operation to get total claimable amount, and it should be done.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 13, 2019

Ok, support for all operations needed for claiming GAS now are in and seem to be working as expected.

vncoelho
vncoelho previously approved these changes Mar 13, 2019
Copy link
Member

@vncoelho vncoelho left a comment

Choose a reason for hiding this comment

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

I also tested here and it is working brilliantly. If there are some errors they would be minors and we can fix in the next steps.
Thanks and congratulation for this game changing PR and dedication, @jsolman.

@jsolman
Copy link
Contributor Author

jsolman commented Mar 13, 2019

@vncoelho
Maybe we can create a 2.10.1 branch as you suggested elsewhere; I will not merge this as it references a CI NuGet build.

@jsolman jsolman changed the base branch from master to plugins-2.10.1 March 14, 2019 18:23
@jsolman jsolman merged commit 4a37c19 into plugins-2.10.1 Mar 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants