An experimental protocol upgrade introducing restricted spending permissions, native batch transfers and improved Resource Credit efficiency.
Over the past several days, I've been working on a set of changes to the Hive blockchain. I wanted to address two things that I think could be improved at the protocol level: how accounts delegate financial permissions and how Hive processes transfers involving multiple accounts.
The result is an experimental implementation of Scoped Authorities and Compressed Batch Transfers, developed directly in the Hive C++ codebase.
I've added four protocol operations, persistent authorization records, spending limits enforced by consensus, and a batch transfer mechanism supporting up to 100 inputs and 100 outputs.
I've also integrated the necessary Resource Credit accounting, database API support, account history handling and tests.
Everything is currently implemented under a single experimental HF30 activation.
HF30 is only the identifier I'm using in my development branch. This isn't an officially proposed or scheduled Hive hardfork, and none of these changes are active on mainnet.
My intention is to make the implementation available for technical review and see whether these changes could eventually become part of Hive.
1. What I'm Trying to Solve
Hive already has a fairly flexible authority system. Accounts can delegate permissions, use weighted authorities and include multiple operations in a single transaction.
However, there are two limitations I wanted to address.
1.1. Financial permissions are too broad
Hive has three primary authority levels:
- Owner
- Active
- Posting
Financial operations generally require active authority.
An account can add another account to its active authority structure, but there's no native way to restrict how much that account is allowed to spend.
For example, suppose Alice wants to let a payment processor spend a maximum of 50 HBD per day.
She could delegate active authority, but that would grant considerably more control than the payment processor actually needs.
The other option is to enforce the spending limit through the application's backend.
That works as an application policy, but the blockchain itself doesn't enforce the restriction. A compromised or incorrectly implemented backend could bypass it.
I wanted to introduce a way for Alice to authorize payments without giving another account unrestricted control over her funds.
1.2. Transfers still contain unnecessary overhead
Hive already allows multiple transfer_operation instances inside one transaction.
If I want to send HBD to 100 accounts, I can create one transaction containing 100 transfer operations.
That's more efficient than broadcasting 100 independent transactions, but every transfer still carries its own operation data.
The source account, destination, asset information and other fields are repeated throughout the transaction.
I wanted to see how much of that overhead could be eliminated by implementing a native batch operation.
I also wanted to support something that conventional transfers don't express as one operation: multiple accounts contributing funds to multiple recipients.
2. Scoped Authorities
The first feature is a new authorization mechanism called Scoped Authorities.
Rather than changing how Hive's existing active authority works, I introduced a separate system for restricted transfers of liquid HIVE and HBD.
I added three operations:
create_scoped_authority_operationrevoke_scoped_authority_operationscoped_transfer_operation
The basic idea is straightforward.
An account creates a grant authorizing another account to spend funds under specific conditions.
The authorized account signs transactions with its own credentials, and Hive checks the restrictions before executing the transfer.
2.1. Example
Suppose Alice wants to authorize hivedebit to process payments.
She creates a grant with these conditions:
| Parameter | Value |
|---|---|
| Grantor | alice |
| Authorized account | hivedebit |
| Asset | HBD |
| Maximum per transfer | 5.000 HBD |
| Maximum per period | 50.000 HBD |
| Period duration | 86,400 seconds |
| Total spending allowance | 250.000 HBD |
| Expiration | 7 days |
| Allowed recipients | merchant1, merchant2 |
Once Alice's grant is confirmed, HiveDebit can submit transfers signed with its own active authority.
If it tries to send 3 HBD to merchant1, the transfer is accepted as long as the remaining conditions are satisfied.
If it tries to send 10 HBD, the blockchain rejects it.
If it tries to send money to an account outside the allowed recipient list, the transfer is also rejected.
If the grant reaches its periodic or lifetime spending limit, no additional funds can be transferred through it.
The authorization expires automatically when its validity period ends.
Recipient restrictions are optional. A grant can permit transfers to any account while still enforcing its spending and expiration limits.
All of this happens during normal consensus execution. There's no external service responsible for deciding whether the transaction is authorized.
2.2. Spending counters
Each grant maintains two spending counters:
- The total amount spent throughout the grant's lifetime.
- The amount spent during the current period.
It also stores the period index used for calculating periodic allowances.
Periods are calculated using the grant's starting timestamp and the blockchain's consensus time.
For example, a grant with a period duration of 86,400 seconds has spending windows lasting 24 hours.
When a new period begins, the periodic counter resets. The lifetime counter doesn't.
All balances and spending limits use Hive's existing integer asset representation. I haven't introduced floating point calculations into consensus.
That matters because every node must independently reach the same result when evaluating a transaction.
2.3. What an authorized account cannot do
A Scoped Authority doesn't grant the same permissions as active authority.
The authorized account cannot use the grant to change the grantor's keys, modify account authorities, increase its spending allowance or extend the expiration.
It also cannot create additional grants on behalf of the grantor or use the permission for unrelated financial operations.
A scoped transfer must explicitly reference an existing grant, and that grant must satisfy every applicable restriction.
This keeps the new permission mechanism separate from Hive's unrestricted financial authority model.
3. Grant Management and Expiration
Another part I had to address was how grants are stored and removed.
My initial implementation limited each account to 100 grant records.
The problem was that revoking a grant didn't remove the record. Expired grants also remained in the database.
After creating 100 grants, an account would eventually be unable to create any more, even if every previous grant had expired.
That wasn't a reasonable design for applications issuing temporary permissions.
I changed the lifecycle so that an account can maintain up to 100 live grants without permanently exhausting that capacity.
3.1. How cleanup works
When a new grant is created, Hive examines the grantor's existing records.
Any grant that has been revoked or has already expired can be removed.
Active grants are never deleted to make room for new ones.
This cleanup is deterministic and occurs during grant creation. It doesn't require a background process or an external service.
An account can therefore create 100 grants, revoke 50 and subsequently create another 50.
3.2. Preventing grant ID reuse
Deleting grants introduces another concern.
If an old grant ID becomes available again, an application might accidentally reference a completely different authorization using an identifier it previously trusted.
To prevent this, I added a persistent Chainbase object that tracks the highest grant ID issued by each account.
New IDs must increase monotonically.
Deleting an expired or revoked grant doesn't make its identifier available again.
The implementation also handles the uint32_t maximum without allowing the identifier to wrap around.
This means the identifier space is still technically finite, but the original limit of 100 grants over an account's entire lifetime is gone.
3.3. Rollback behavior
Grant creation, revocation, spending counters, metadata updates and cleanup all participate in Hive's normal transaction undo mechanism.
If a transaction fails, the corresponding state changes are reverted.
The same applies when blockchain state is rolled back.
I added tests for grant replacement, expiration, identifier reuse, maximum identifier values, failed transactions and block rollback.
These lifecycle rules are included in the same experimental HF30 activation as the rest of the implementation.
4. Compressed Batch Transfers
The second major change is:
compressed_batch_transfer_operation
This operation allows multiple source accounts and multiple destination accounts to participate in a single native transfer.
The current implementation supports a maximum of 100 inputs and 100 outputs, using one HIVE or HBD asset per operation.
Hive doesn't use Bitcoin's UTXO model, and I'm not attempting to introduce UTXOs.
The inputs represent account balances being debited. The outputs represent account balances being credited.
4.1. Example: two inputs and three outputs
Suppose Alice contributes 40 HBD and Bob contributes 60 HBD.
Inputs
| Account | Amount |
|---|---|
| alice | 40.000 HBD |
| bob | 60.000 HBD |
| Total | 100.000 HBD |
Outputs
| Account | Amount |
|---|---|
| carlos | 50.000 HBD |
| diana | 30.000 HBD |
| pedro | 20.000 HBD |
| Total | 100.000 HBD |
The evaluator verifies that the sum of all inputs equals the sum of all outputs.
It also checks that each source account has enough funds and that all necessary authorizations are present.
The operation is atomic. If an input fails validation, the transaction cannot partially execute the remaining payments.
This allows several accounts to contribute funds without requiring a separate transfer operation for every movement.
4.2. Authorization
For normal inputs, each contributing account must satisfy its active authority requirements.
If Alice and Bob contribute funds independently, both accounts must authorize their respective debits.
The batch operation doesn't allow one account to spend another account's funds without permission.
However, I also integrated Scoped Authorities into the operation.
Instead of requiring a direct active authorization, an input can reference a valid spending grant.
This means multiple accounts can authorize the same operator to process payments, and the operator can execute one batch while Hive checks each account's individual limits.
5. Combining Scoped Authorities With Batch Transfers
Combining these two features required some additional work.
When a batch has several inputs and outputs, the blockchain needs an unambiguous way to determine which source account is funding each recipient.
This is particularly important when a Scoped Authority includes recipient restrictions.
Suppose Alice allows payments only to Merchant A and Bob allows payments only to Merchant B.
A batch shouldn't be able to combine their funds and indirectly send Alice's authorized balance to Merchant B.
5.1. Deterministic attribution
I implemented deterministic attribution based on canonical ordering.
Inputs and outputs must follow the ordering rules defined by the operation.
The evaluator processes the input amounts against the output amounts in sequence.
A source can fund multiple recipients, and a recipient can receive portions funded by more than one source.
For example, imagine the following amounts:
Alice contributes 40 HBD and Bob contributes 60 HBD.
The outputs are:
- Carlos receives 50 HBD.
- Diana receives 30 HBD.
- Pedro receives 20 HBD.
The attribution would be:
- Alice funds 40 HBD of Carlos's payment.
- Bob funds the remaining 10 HBD sent to Carlos.
- Bob funds the 30 HBD sent to Diana.
- Bob funds the 20 HBD sent to Pedro.
If Bob's Scoped Authority doesn't permit payments to Carlos, the entire batch is rejected.
This provides a deterministic way to enforce recipient restrictions even when several source accounts contribute to the same operation.
It's also one of the parts I'd particularly like other Hive developers to review, since the correctness of this attribution directly affects authorization security.
5.2. Spending limits in batches
Scoped inputs are checked against the same restrictions as individual scoped transfers.
These include the maximum spending amount, periodic allowance, lifetime allowance, expiration, revocation and permitted recipients.
A batch doesn't provide a separate path for bypassing those rules.
The evaluator validates the applicable conditions before updating account balances and grant counters.
I've tested this behavior through the consensus test suite and signed transactions on an isolated development chain.
6. Binary Serialization
I wanted the batch operation to be smaller without introducing unnecessary complexity into Hive's serialization format.
I didn't implement a separate compression algorithm.
Instead, the operation uses Hive's existing binary serialization infrastructure while eliminating repeated fields.
For example, a batch can use one shared asset symbol rather than including the same asset information in every transfer.
Sources and destinations are represented through compact vectors, amounts use the existing integer representation, and scoped inputs include their grant references.
The operation also uses one shared memo.
This reduces the amount of repeated data, particularly when one account is distributing funds to many recipients.
The main benefit comes from representing several balance movements as one operation, rather than serializing multiple independent transfer structures.
I also kept the input and output counts bounded and required canonical ordering to make transaction interpretation deterministic.
7. Resource Credit Benchmarks
I wanted actual measurements before making any claim about RC savings.
For that reason, I added a benchmark suite comparing four different ways of executing equivalent transfers.
A. Independent transfers
Each payment is submitted as a separate transaction.
B. Standard grouped transfers
Multiple existing transfer_operation instances are included in a single transaction.
C. Compressed Active Batch
One compressed batch operation is used, with the contributing accounts authorizing their inputs through their existing active authorities.
D. Compressed Scoped Batch
The same native batch operation is used, but the contributing accounts have previously issued restricted spending grants to an authorized actor.
The distinction between Active Batch and Scoped Batch is important.
Both use the same compressed batch operation. The difference is authorization.
With Active Batch, every independent source account must satisfy its active authority requirements.
With Scoped Batch, the source accounts can authorize the same actor beforehand. That actor can then sign the batch while the blockchain verifies each grant.
When only one account is sending money, Active Batch can be slightly cheaper because it doesn't need to access a grant.
When many independent accounts contribute funds, Scoped Batch can save considerable signature overhead.
The benchmark measures serialized bytes, signature counts, resource vectors, confirmed RC charges, execution time, memory usage and balance adjustments.
The figures below were measured in the development environment using the recorded RC pool parameters. They should not be interpreted as fixed mainnet costs.
7.1. One input and 100 outputs
I compared the cost of distributing funds from one account to 100 recipients.
| Method | Serialized bytes | Confirmed RC |
|---|---|---|
| 100 independent transactions | 13,400 | 738,773,100 |
| Standard transfers in one transaction | 5,678 | 292,174,541 |
| Compressed Active Batch | 2,115 | 110,814,161 |
| Compressed Scoped Batch | 2,125 | 111,349,014 |
Compared with standard grouped transfers, Compressed Active Batch achieved:
- 62.75% less serialized data.
- 62.07% less RC consumption.
Compared with 100 independent transactions, the RC reduction was approximately 85%.
However, I think the most relevant comparison is against standard transfers already grouped into a single transaction, because Hive supports that today.
For this particular scenario, Active Batch is slightly cheaper than Scoped Batch. With one source account, there is little signature overhead to eliminate, while checking a scoped grant introduces additional work.
7.2. Other input and output configurations
I also benchmarked transactions involving multiple source accounts.
The following table shows RC consumption in millions.
| Inputs → Outputs | Standard grouped RC | Active Batch RC | Scoped Batch RC |
|---|---|---|---|
| 1 → 3 | 10.29 M | 7.69 M | 8.12 M |
| 1 → 10 | 27.97 M | 14.44 M | 14.90 M |
| 1 → 100 | 292.17 M | 110.81 M | 111.35 M |
| 3 → 2 | 45.59 M | 41.28 M | 26.14 M |
| 10 → 10 | 154.21 M | 141.54 M | 67.36 M |
| 100 → 100 | 1,668.37 M | 1,490.47 M | 599.71 M |
The difference becomes more interesting with many source accounts.
For a batch involving 100 inputs and 100 outputs, the Active Batch configuration consumed approximately 1.49 billion RC.
The Scoped Batch configuration consumed approximately 599.71 million RC.
That's about 59.8% less RC than Active Batch.
In this benchmark, the active configuration required signatures from 100 independent sources.
The scoped configuration used a single authorized actor signature because the source accounts had already established their individual grants.
Hive still checked the restrictions associated with every scoped input.
This isn't a reduction in the number of balances being processed. The savings come largely from reducing transaction signature overhead and the amount of repeated authorization data.
There's an important qualification: creating those grants also consumes RC.
The figures above compare the batch transactions themselves, not the combined cost of creating all the grants and executing the first batch.
7.3. RC pricing
I haven't attempted to make a batch of 100 payments cost the same as one ordinary transfer.
Even with compact serialization, a batch involving many accounts requires balance lookups, authorization checks and state updates.
The implementation charges additional execution weight according to the number of inputs and outputs, as well as the work required to access scoped authorization state.
Normal transaction size and signature costs still apply.
The objective is to avoid paying for redundant serialization and repeated operation overhead while still accounting for the resources the blockchain actually consumes.
I would particularly appreciate an independent review of the new RC weights.
Passing benchmarks shows that the accounting is reproducible under the test conditions, but it doesn't establish that the pricing is economically optimal.
7.4. Cost of creating grants
Scoped Authorities introduce an initial cost.
Each grant is a transaction that consumes RC and creates persistent state.
If an account creates a grant and uses it only once, the scoped configuration may not provide a net RC saving.
The benchmark documentation includes grant creation costs and estimates how many repeated batches would be needed to amortize them.
Depending on the configuration, that can require many executions.
For that reason, I see Scoped Authorities primarily as an authorization and security improvement.
Their potential RC advantage is most relevant when many accounts reuse their grants for repeated batch operations.
8. Integration With Hive
I implemented the changes using Hive's existing protocol, evaluator and database architecture.
The four new operations are:
create_scoped_authority_operationrevoke_scoped_authority_operationscoped_transfer_operationcompressed_batch_transfer_operation
The changes affect several components.
Protocol definitions
The operation structures, validation requirements, authority handling and serialization are defined in the protocol library.
Chain evaluators
These handle grant creation, restricted transfers, batch execution, spending counters and revocation.
Chainbase state
Two new persistent object types store the grants and the highest issued grant identifiers for each grantor.
Resource Credits
I integrated resource accounting for the new operations, including execution work and delegated authorization.
Database API
I added database_api.get_scoped_authorities so applications can inspect authorization records and their current state.
Account history
The new operations are included in the relevant account history and impacted account handling.
8.1. Hardfork activation
All four operations and the grant lifecycle rules use one experimental HF30 activation.
An earlier development iteration separated lifecycle changes into another activation. I removed that separation and consolidated everything into the initial experimental hardfork before preparing the proposal.
8.2. Compatibility
I preserved the existing historical operation identifiers.
I also compared the binary serialization of a legacy transfer against an untouched upstream checkout.
Both versions produced identical serialized bytes for that transaction.
This is a useful compatibility check, but it doesn't cover every historical operation type.
A complete upstream review would still need to examine serialization, operation classification, resource accounting and activation behavior.
9. Testing
Since these changes modify consensus behavior, I spent a significant part of the work on testing rather than just implementing the new operations.
9.1. Automated tests
The current consolidated implementation has the following recorded results:
| Test category | Result |
|---|---|
| Chain test suite | 526 passed, 1 optional benchmark skipped |
| Consensus assertions | 1,835,538 passed |
| Focused Scoped Authority and Batch tests | 29 passed |
| Plugin tests | 102 passed |
| Plugin assertions | 7,134 passed |
| Configuration tests | 3 passed |
| RC benchmark assertions | 904 passed |
The focused and configuration tests overlap with the full chain suite and shouldn't be counted as additional independent cases.
The tests cover authorization failures, spending limits, expiration, revocation, grant pruning, identifier reuse, balance conservation, transaction rollback, batch execution and other consensus behavior.
I also reviewed the source changes for unnecessary abstractions, redundant comments and inconsistencies with existing Hive C++ conventions.
9.2. Signed RPC transactions
I wanted to verify that the implementation worked through normal signed transactions, not only direct evaluator tests.
I ran an isolated development blockchain and executed grant creation, restricted transfers, batch transfers, revocation, expiration and grant replacement.
Some confirmed transactions from that test chain include:
| Operation | Transaction ID | Block |
|---|---|---|
| Scoped transfer | 1016152cc3639d568f94f8380af679fb8c579655 | 76 |
| Scoped batch | a8d8a3df7731784c2f63ef04cc0b6dc877fcfa6c | 80 |
| Active batch | b4c481a60e87424558e1a9a842f99d9f56819db1 | 88 |
| Revocation | 194ec03b1d8818c4678cb1ae2743ac9d7ecee23b | 93 |
Transfers exceeding their limits, using unauthorized recipients or referencing expired grants were rejected.
I checked that these rejected operations didn't get included in blocks or incorrectly modify balances and spending counters.
9.3. Snapshot and replay
I also tested whether the new persistent authorization state could be reconstructed correctly.
I created a fresh development chain with unified HF30 activated at block 1.
The chain contained multiple grantors, actors, active and expired grants, revoked grants, spending counters, pruning and replacement identifiers.
At block 170, the original node, an independent snapshot restoration and a separate replay from genesis all reported the same block ID:
000000aae264e0ff0248dd3cab78bb2a01e0382d
I compared saved API state projections from the three environments.
They matched byte for byte, including:
- Account balances and authorities.
- Retained grant records.
- Spending counters.
- Grant expiration and revocation status.
- Highest issued grant identifiers.
- Blockchain head information.
This verifies the compared state within the tested environment. It doesn't mean that the underlying Chainbase database files were compared directly.
9.4. Two node synchronization
I also ran two independent development nodes.
One node was stopped while the other continued generating blocks containing grant lifecycle operations.
After restarting the stopped node, it synchronized with the primary.
Both reported the same block and corresponding consensus state at block 159:
0000009fae5d2791a746293a50983d9c614c343e
This included pruning and grant replacement, which I considered especially important because those operations modify persistent grant metadata.
9.5. Mainnet isolation
I built the production configuration separately.
All four experimental operations reached their corresponding evaluator paths in an isolated environment and returned the expected errors indicating that they were disabled on mainnet.
These were local runtime rejection tests, not signed mainnet transactions.
I didn't use production private keys or broadcast any transactions to the public blockchain.
10. Code Size and Implementation
I tried to keep the implementation as close as possible to Hive's existing architecture.
The new functionality reuses the protocol's serialization system, authority checks, balance handling, Chainbase objects and transaction rollback mechanisms.
I haven't introduced a separate execution environment, virtual machine, new signature algorithm or external database.
The development branch contains the protocol changes, tests, benchmark data and documentation.
A substantial part of the added code consists of test cases rather than production logic.
I also went through the implementation to remove unnecessary references, redundant checks and comments that didn't add useful information.
I think keeping consensus changes relatively small and understandable is important, especially when other developers need to review their security implications.
11. What Could This Be Used For?
I see several practical applications for these changes.
Payment processors
A payment service could receive limited permissions from users without requiring unrestricted active authority.
Recurring payments
Users could authorize a specific spending amount over a defined period. Applications would still need to submit the transactions, but Hive would enforce the spending limits.
Mass payments
An account could distribute HIVE or HBD to many recipients through one compact operation.
Treasury management
Several accounts could jointly contribute funds to a single payment operation, with each source independently authorized.
Wallet security
Wallets could offer restricted permissions for applications that need to initiate payments without receiving full financial control.
Delegated batch processing
Multiple users could authorize one operator to execute payments on their behalf while keeping individual spending and recipient restrictions.
None of this requires changing Hive into a UTXO blockchain.
These are additional primitives built around its existing account model.
12. What Still Needs Review
I've completed the implementation and the tests described above, but I don't consider the code ready for mainnet deployment.
There are several areas where I would want additional scrutiny.
Authorization security
The grant model, actor authentication, permission boundaries and interaction with active authority should receive an independent security review.
Batch attribution
The source and destination attribution logic needs careful examination, especially when different grants have different recipient restrictions.
Resource Credits
The new execution weights need review from developers familiar with Hive's resource economics. I want to ensure the operation can't be used to consume excessive resources at an artificially low RC cost.
Persistent state
The grant cleanup mechanism is bounded, but its state requirements and long term economic impact should be evaluated.
Serialization
The historical transfer comparison passed, but broader compatibility tests would be valuable.
Hardfork integration
The implementation still needs an officially assigned activation point, upstream review and the normal hardfork release process.
An independent audit is also necessary before considering the code for production use.
13. Preparing the Upstream Contribution
The implementation is currently maintained in a development branch based on Hive's source code.
I've documented the operation formats, authorization rules, spending counters, grant lifecycle, batch attribution, RC methodology, benchmark measurements, compatibility considerations and test procedures.
The repository also contains the raw benchmark results and the testing records.
I consolidated the changes into one experimental HF30 activation because I want the authorization system, batch transfers and grant lifecycle rules to be reviewed as a coherent implementation.
Of course, that doesn't mean upstream maintainers have to accept the design exactly as it is.
I'm open to changes in the operation structures, RC accounting, authorization semantics or even separating the features if that makes sense for Hive's development process.
What I want to contribute is an actual implementation that developers can inspect, build, benchmark and criticize.
I think Scoped Authorities could provide a useful improvement to Hive's financial authorization model, and the batch operation already shows measurable efficiency gains under the tested conditions.
Both features are implemented, and I've tried to document the technical decisions and their limitations rather than just publish performance claims.
14. Request to BlockTrades
@blocktrades, I'd really appreciate your technical feedback on this experimental HF30 implementation, particularly the consensus design, authorization model and RC optimizations.
I'd also appreciate an invitation to the gitlab so I can submit the code, benchmarks and documentation through a Draft Merge Request for proper upstream review.
And if it's not too much to ask, a pancake would be nice too.