Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
29f92bed
Commit
29f92bed
authored
4 years ago
by
Karl Floersch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finish custom encoding
parent
d0831b40
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
173 additions
and
210 deletions
+173
-210
OVM_CanonicalTransactionChain.sol
...stic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol
+95
-119
iOVM_CanonicalTransactionChain.sol
...ic-ethereum/iOVM/chain/iOVM_CanonicalTransactionChain.sol
+12
-13
OVM_CanonicalTransactionChain.spec.ts
...contracts/OVM/chain/OVM_CanonicalTransactionChain.spec.ts
+66
-78
No files found.
packages/contracts/contracts/optimistic-ethereum/OVM/chain/OVM_CanonicalTransactionChain.sol
View file @
29f92bed
...
...
@@ -35,6 +35,7 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_Ba
uint256 constant public BATCH_CONTEXT_SIZE = 16;
uint256 constant public BATCH_CONTEXT_LENGTH_POS = 12;
uint256 constant public BATCH_CONTEXT_START_POS = 15;
uint256 constant public TX_DATA_HEADER_SIZE = 15;
/*************
...
...
@@ -234,106 +235,87 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_Ba
override
public
{
bytes32 firstCalldataWord;
uint40 _shouldStartAtBatch;
uint24 _totalElementsToAppend;
uint24 _contextsLength;
assembly {
// First 5 bytes after MethodId is _shouldStartAtBatch
_shouldStartAtBatch := shr(216, calldataload(4))
// Next 3 bytes is _totalElementsToAppend
_totalElementsToAppend := shr(232, calldataload(9))
// And the last 3 bytes is the _contextsLength
_contextsLength := shr(232, calldataload(12))
}
console.log("_shouldStartAtBatch");
console.log(_shouldStartAtBatch);
console.log("_totalElementsToAppend");
console.log(_totalElementsToAppend);
// numBatchContexts header always starts at byte 12
// 4[method_id] + 5[_shouldStartAtBatch] + 3[_totalElementsToAppend]
uint numBatchContexts;
assembly {
// 3 byte numSubsequentQueueTransactions
numBatchContexts := shr(232, calldataload(BATCH_CONTEXT_LENGTH_POS))
require(
_shouldStartAtBatch == getTotalBatches(),
"Actual batch start index does not match expected start index."
);
require(
msg.sender == sequencer,
"Function can only be called by the Sequencer."
);
require(
_contextsLength > 0,
"Must provide at least one batch context."
);
require(
_totalElementsToAppend > 0,
"Must append at least one element."
);
bytes32[] memory leaves = new bytes32[](_totalElementsToAppend);
uint32 transactionIndex = 0;
uint32 numSequencerTransactionsProcessed = 0;
uint32 nextSequencerTransactionPosition = uint32(BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * _contextsLength);
(, uint32 nextQueueIndex) = _getLatestBatchContext();
for (uint32 i = 0; i < _contextsLength; i++) {
BatchContext memory context = _getBatchContext(i);
_validateBatchContext(context, nextQueueIndex);
for (uint32 i = 0; i < context.numSequencedTransactions; i++) {
bytes memory txData = _getTransactionData(nextSequencerTransactionPosition);
leaves[transactionIndex] = _hashTransactionChainElement(
TransactionChainElement({
isSequenced: true,
queueIndex: 0,
timestamp: context.timestamp,
blockNumber: context.blockNumber,
txData: txData
})
);
nextSequencerTransactionPosition += uint32(TX_DATA_HEADER_SIZE + txData.length);
numSequencerTransactionsProcessed++;
transactionIndex++;
}
for (uint32 i = 0; i < context.numSubsequentQueueTransactions; i++) {
leaves[transactionIndex] = _getQueueLeafHash(nextQueueIndex);
nextQueueIndex++;
transactionIndex++;
}
}
console.log("numBatchContexts");
// Grab a batch context
BatchContext memory batchCtx = _getBatchContext(0);
// Grab transaction data
bytes memory transaction = _getTransactionData(0);
console.logBytes(transaction);
// require(
// _shouldStartAtBatch == getTotalBatches(),
// "Actual batch start index does not match expected start index."
// );
// require(
// msg.sender == sequencer,
// "Function can only be called by the Sequencer."
// );
// require(
// _contexts.length > 0,
// "Must provide at least one batch context."
// );
// require(
// _totalElementsToAppend > 0,
// "Must append at least one element."
// );
// bytes32[] memory leaves = new bytes32[](_totalElementsToAppend);
// uint32 transactionIndex = 0;
// uint32 numSequencerTransactionsProcessed = 0;
// (, uint32 nextQueueIndex) = _getLatestBatchContext();
// for (uint32 i = 0; i < _contexts.length; i++) {
// BatchContext memory context = _contexts[i];
// _validateBatchContext(context, nextQueueIndex);
// for (uint32 i = 0; i < context.numSequencedTransactions; i++) {
// leaves[transactionIndex] = _hashTransactionChainElement(
// TransactionChainElement({
// isSequenced: true,
// queueIndex: 0,
// timestamp: context.timestamp,
// blockNumber: context.blockNumber,
// txData: _transactions[numSequencerTransactionsProcessed]
// })
// );
// numSequencerTransactionsProcessed++;
// transactionIndex++;
// }
// for (uint32 i = 0; i < context.numSubsequentQueueTransactions; i++) {
// leaves[transactionIndex] = _getQueueLeafHash(nextQueueIndex);
// nextQueueIndex++;
// transactionIndex++;
// }
// }
// require(
// numSequencerTransactionsProcessed == _transactions.length,
// "Not all sequencer transactions were processed."
// );
// require(
// transactionIndex == _totalElementsToAppend,
// "Actual transaction index does not match expected total elements to append."
// );
// uint256 numQueuedTransactions = _totalElementsToAppend - numSequencerTransactionsProcessed;
// _appendBatch(
// Lib_MerkleRoot.getMerkleRoot(leaves),
// _totalElementsToAppend,
// numQueuedTransactions
// );
// emit SequencerBatchAppended(
// nextQueueIndex - numQueuedTransactions,
// numQueuedTransactions
// );
require(
transactionIndex == _totalElementsToAppend,
"Actual transaction index does not match expected total elements to append."
);
uint256 numQueuedTransactions = _totalElementsToAppend - numSequencerTransactionsProcessed;
_appendBatch(
Lib_MerkleRoot.getMerkleRoot(leaves),
_totalElementsToAppend,
numQueuedTransactions
);
emit SequencerBatchAppended(
nextQueueIndex - numQueuedTransactions,
numQueuedTransactions
);
}
...
...
@@ -341,18 +323,23 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_Ba
* Internal Functions *
**********************/
/**
* Returns the BatchContext located at a particular index.
* @param _index The index of the BatchContext
* @return _context The BatchContext at the specified index.
*/
function _getBatchContext(
uint _
numProcessed
uint _
index
)
internal
view
returns (
BatchContext memory context
BatchContext memory
_
context
)
{
// Batch contexts always start at byte 12:
// 4[method_id] + 5[_shouldStartAtBatch] + 3[_totalElementsToAppend] + 3[numBatchContexts]
uint contextPosition = 15 + _
numProcessed
* BATCH_CONTEXT_SIZE;
uint contextPosition = 15 + _
index
* BATCH_CONTEXT_SIZE;
uint numSequencedTransactions;
uint numSubsequentQueueTransactions;
uint ctxTimestamp;
...
...
@@ -367,52 +354,41 @@ contract OVM_CanonicalTransactionChain is iOVM_CanonicalTransactionChain, OVM_Ba
// 5 byte blockNumber
ctxBlockNumber := shr(216, calldataload(add(contextPosition, 11)))
}
console.log("RETURNING BATCH:");
console.log("numSequencedTransactions");
console.log(numSequencedTransactions);
console.log("numSubsequentQueueTransactions");
console.log(numSubsequentQueueTransactions);
console.log("timestamp");
console.log(ctxTimestamp);
console.log("blockNumber");
console.log(ctxBlockNumber);
return BatchContext({
numSequencedTransactions: numSequencedTransactions,
numSubsequentQueueTransactions: numSubsequentQueueTransactions,
timestamp: ctxTimestamp,
blockNumber: ctxBlockNumber,
index: _numProcessed
blockNumber: ctxBlockNumber
});
}
/**
* Returns the transaction data located at a particular start position in calldata.
* @param _startPosition Start position in calldata (represented in bytes).
* @return _transactionData The transaction data for this particular element.
*/
function _getTransactionData(
uint _
numProcessed
uint _
startPosition
)
internal
view
returns (
bytes memory transactionData
bytes memory
_
transactionData
)
{
uint numBatchContexts;
assembly {
numBatchContexts := shr(232, calldataload(BATCH_CONTEXT_LENGTH_POS))
}
uint startPosition = BATCH_CONTEXT_START_POS + BATCH_CONTEXT_SIZE * numBatchContexts;
uint transactionSize;
assembly {
// 3 byte transactionSize
transactionSize := shr(232, calldataload(startPosition))
transactionSize := shr(232, calldataload(
_
startPosition))
// Initialize transactionData at the free memory pointer 0x40
transactionData := mload(0x40)
// Initialize
_
transactionData at the free memory pointer 0x40
_
transactionData := mload(0x40)
// Store the length as the first word to conform with `bytes memory`
mstore(transactionData, transactionSize)
mstore(
_
transactionData, transactionSize)
// Store the rest of the transaction
calldatacopy(add(
transactionData, 32), add(
startPosition, 3), transactionSize)
calldatacopy(add(
_transactionData, 32), add(_
startPosition, 3), transactionSize)
}
return transactionData;
return
_
transactionData;
}
/**
...
...
This diff is collapsed.
Click to expand it.
packages/contracts/contracts/optimistic-ethereum/iOVM/chain/iOVM_CanonicalTransactionChain.sol
View file @
29f92bed
...
...
@@ -46,7 +46,6 @@ interface iOVM_CanonicalTransactionChain is iOVM_BaseChain {
uint256 numSubsequentQueueTransactions;
uint256 timestamp;
uint256 blockNumber;
uint256 index;
}
struct TransactionChainElement {
...
...
@@ -96,17 +95,17 @@ interface iOVM_CanonicalTransactionChain is iOVM_BaseChain {
uint256 _numQueuedTransactions
) external;
/
/ /
**
//
* Allows the sequencer to append a batch of transactions.
// * @param _transactions Array of raw transaction data
.
// * @param _contexts Array of batch contexts
.
// * @param _shouldStartAtBatch Specific batch we expect to start appending to
.
// * @param _totalElementsToAppend Total number of batch elements we expect to append
.
//
*/
function appendSequencerBatch(
// uint
256
_shouldStartAtBatch,
// uint _totalElementsToAppend,
// BatchContext[]
memory
_contexts,
// bytes[]
memory _transaction
s
/**
* Allows the sequencer to append a batch of transactions.
* param _shouldStartAtBatch Specific batch we expect to start appending to
.
* param _totalElementsToAppend Total number of batch elements we expect to append
.
* param _contexts Array of batch contexts
.
* param _transactionDataFields Array of raw transaction data
.
*/
function appendSequencerBatch(
// USES CUSTOM ENCODING FOR EFFICIENCY PURPOSES
// uint
40
_shouldStartAtBatch,
// uint
24
_totalElementsToAppend,
// BatchContext[] _contexts,
// bytes[]
_transactionDataField
s
) external;
}
This diff is collapsed.
Click to expand it.
packages/contracts/test/contracts/OVM/chain/OVM_CanonicalTransactionChain.spec.ts
View file @
29f92bed
...
...
@@ -111,20 +111,16 @@ const encodeAppendSequencerBatch = (
):
string
=>
{
let
encoding
:
string
const
encodedShouldStartAtBatch
=
remove0x
(
BigNumber
.
from
(
b
.
shouldStartAtBatch
).
toHexString
()).
padStart
(
10
,
'
0
'
)
console
.
log
(
'
encodedShouldStartAtBatch
'
,
encodedShouldStartAtBatch
)
const
encodedTotalElementsToAppend
=
remove0x
(
BigNumber
.
from
(
b
.
totalElementsToAppend
).
toHexString
()).
padStart
(
6
,
'
0
'
)
console
.
log
(
'
encodedTotalElementsToAppend
'
,
encodedTotalElementsToAppend
)
const
encodedContextsHeader
=
remove0x
(
BigNumber
.
from
(
b
.
contexts
.
length
).
toHexString
()).
padStart
(
6
,
'
0
'
)
const
encodedContexts
=
encodedContextsHeader
+
b
.
contexts
.
reduce
((
acc
,
cur
)
=>
acc
+
encodeBatchContext
(
cur
),
''
)
console
.
log
(
'
encodedContexts
'
,
encodedContexts
)
const
encodedTransactionData
=
b
.
transactions
.
reduce
((
acc
,
cur
)
=>
{
if
(
cur
.
length
%
2
!==
0
)
throw
new
Error
(
'
Unexpected uneven hex string value!
'
)
const
encodedTxDataHeader
=
remove0x
(
BigNumber
.
from
(
remove0x
(
cur
).
length
/
2
).
toHexString
()).
padStart
(
6
,
'
0
'
)
return
acc
+
encodedTxDataHeader
+
remove0x
(
cur
)
},
''
)
console
.
log
(
'
encodedTransactionData
'
,
encodedTransactionData
)
return
(
encodedShouldStartAtBatch
+
encodedTotalElementsToAppend
+
...
...
@@ -139,7 +135,6 @@ const appendSequencerBatch = async (
):
Promise
<
TransactionResponse
>
=>
{
const
methodId
=
keccak256
(
Buffer
.
from
(
'
appendSequencerBatch()
'
)).
slice
(
2
,
10
)
const
calldata
=
encodeAppendSequencerBatch
(
batch
)
console
.
log
(
'
Generated batch calldata:
'
,
calldata
)
return
OVM_CanonicalTransactionChain
.
signer
.
sendTransaction
({
to
:
OVM_CanonicalTransactionChain
.
address
,
data
:
'
0x
'
+
methodId
+
calldata
,
...
...
@@ -493,30 +488,11 @@ describe('OVM_CanonicalTransactionChain', () => {
)
})
it
.
only
(
'
should revert if expected start does not match current total batches
'
,
async
()
=>
{
const
timestamp
=
(
await
getEthTime
(
ethers
.
provider
))
-
100
const
blockNumber
=
(
await
getNextBlockNumber
(
ethers
.
provider
))
+
100
const
batch
:
AppendSequencerBatchParams
=
{
shouldStartAtBatch
:
99
,
totalElementsToAppend
:
88
,
contexts
:
[
{
numSequencedTransactions
:
69
,
numSubsequentQueueTransactions
:
42
,
timestamp
,
blockNumber
,
},
],
transactions
:
[
'
0x1234
'
],
}
const
res
=
await
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
batch
)
})
it
(
'
should revert if expected start does not match current total batches
'
,
async
()
=>
{
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
[
'
0x1234
'
],
[
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
:
[
'
0x1234
'
],
contexts
:
[
{
numSequencedTransactions
:
0
,
numSubsequentQueueTransactions
:
0
,
...
...
@@ -524,19 +500,19 @@ describe('OVM_CanonicalTransactionChain', () => {
blockNumber
:
0
,
},
],
1234
,
1
)
).
to
.
be
.
revertedWith
(
shouldStartAtBatch
:
1234
,
totalElementsToAppend
:
1
}
)
)
.
to
.
be
.
revertedWith
(
'
Actual batch start index does not match expected start index.
'
)
})
it
(
'
should revert if not called by the sequencer
'
,
async
()
=>
{
await
expect
(
OVM_CanonicalTransactionChain
.
connect
(
signer
).
appendSequencerBatch
(
[
'
0x1234
'
],
[
appendSequencerBatch
(
OVM_CanonicalTransactionChain
.
connect
(
signer
),
{
transactions
:
[
'
0x1234
'
],
contexts
:
[
{
numSequencedTransactions
:
0
,
numSubsequentQueueTransactions
:
0
,
...
...
@@ -544,34 +520,37 @@ describe('OVM_CanonicalTransactionChain', () => {
blockNumber
:
0
,
},
],
0
,
1
)
).
to
.
be
.
revertedWith
(
'
Function can only be called by the Sequencer.
'
)
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
1
}
)
)
.
to
.
be
.
revertedWith
(
'
Function can only be called by the Sequencer.
'
)
})
it
(
'
should revert if no contexts are provided
'
,
async
()
=>
{
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
([
'
0x1234
'
],
[],
0
,
1
)
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
:
[
'
0x1234
'
],
contexts
:
[],
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
1
})
).
to
.
be
.
revertedWith
(
'
Must provide at least one batch context.
'
)
})
it
(
'
should revert if total elements to append is zero
'
,
async
()
=>
{
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
[
'
0x1234
'
],
[
{
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
:
[
'
0x1234
'
],
contexts
:
[{
numSequencedTransactions
:
0
,
numSubsequentQueueTransactions
:
0
,
timestamp
:
0
,
blockNumber
:
0
,
},
],
0
,
0
)
).
to
.
be
.
revertedWith
(
'
Must append at least one element.
'
)
}],
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
0
}
)).
to
.
be
.
revertedWith
(
'
Must append at least one element.
'
)
})
for
(
const
size
of
ELEMENT_TEST_SIZES
)
{
...
...
@@ -590,9 +569,10 @@ describe('OVM_CanonicalTransactionChain', () => {
)
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
[
'
0x1234
'
],
[
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
:
[
'
0x1234
'
],
contexts
:
[
{
numSequencedTransactions
:
0
,
numSubsequentQueueTransactions
:
0
,
...
...
@@ -600,9 +580,9 @@ describe('OVM_CanonicalTransactionChain', () => {
blockNumber
:
0
,
},
],
0
,
1
)
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
1
}
)
).
to
.
be
.
revertedWith
(
'
Older queue batches must be processed before a new sequencer batch.
'
)
...
...
@@ -612,9 +592,9 @@ describe('OVM_CanonicalTransactionChain', () => {
const
timestamp
=
(
await
getEthTime
(
ethers
.
provider
))
+
1000
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
[
'
0x1234
'
],
[
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
:
[
'
0x1234
'
],
contexts
:
[
{
numSequencedTransactions
:
0
,
numSubsequentQueueTransactions
:
0
,
...
...
@@ -622,8 +602,9 @@ describe('OVM_CanonicalTransactionChain', () => {
blockNumber
:
0
,
},
],
0
,
1
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
1
}
)
).
to
.
be
.
revertedWith
(
'
Sequencer transactions timestamp too high.
'
)
})
...
...
@@ -633,9 +614,9 @@ describe('OVM_CanonicalTransactionChain', () => {
const
blockNumber
=
(
await
getNextBlockNumber
(
ethers
.
provider
))
+
100
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
[
'
0x1234
'
],
[
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
:
[
'
0x1234
'
],
contexts
:
[
{
numSequencedTransactions
:
0
,
numSubsequentQueueTransactions
:
0
,
...
...
@@ -643,8 +624,9 @@ describe('OVM_CanonicalTransactionChain', () => {
blockNumber
:
blockNumber
,
},
],
0
,
1
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
1
}
)
).
to
.
be
.
revertedWith
(
'
Sequencer transactions blockNumber too high.
'
)
})
...
...
@@ -674,12 +656,12 @@ describe('OVM_CanonicalTransactionChain', () => {
it
(
'
should append the given number of transactions
'
,
async
()
=>
{
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
,
contexts
,
0
,
size
)
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
size
}
)
)
.
to
.
emit
(
OVM_CanonicalTransactionChain
,
'
SequencerBatchAppended
'
)
.
withArgs
(
0
,
0
)
...
...
@@ -722,11 +704,12 @@ describe('OVM_CanonicalTransactionChain', () => {
it
(
'
should append the batch
'
,
async
()
=>
{
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
,
contexts
,
0
,
size
*
2
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
size
*
2
}
)
)
.
to
.
emit
(
OVM_CanonicalTransactionChain
,
'
SequencerBatchAppended
'
)
...
...
@@ -762,12 +745,12 @@ describe('OVM_CanonicalTransactionChain', () => {
it
(
'
should append the batch
'
,
async
()
=>
{
await
expect
(
OVM_CanonicalTransactionChain
.
appendSequencerBatch
(
appendSequencerBatch
(
OVM_CanonicalTransactionChain
,
{
transactions
,
contexts
,
0
,
size
+
spacing
)
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
size
+
spacing
}
)
)
.
to
.
emit
(
OVM_CanonicalTransactionChain
,
'
SequencerBatchAppended
'
)
.
withArgs
(
0
,
spacing
)
...
...
@@ -802,9 +785,14 @@ describe('OVM_CanonicalTransactionChain', () => {
return
'
0x
'
+
'
12
'
+
'
34
'
.
repeat
(
idx
)
})
await
OVM_CanonicalTransactionChain
.
connect
(
await
appendSequencerBatch
(
OVM_CanonicalTransactionChain
.
connect
(
sequencer
).
appendSequencerBatch
(
transactions
,
contexts
,
0
,
size
)
),
{
transactions
,
contexts
,
shouldStartAtBatch
:
0
,
totalElementsToAppend
:
size
})
})
it
(
`should return
${
size
}
`
,
async
()
=>
{
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment