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
f6c20be2
Commit
f6c20be2
authored
Oct 12, 2020
by
Karl Floersch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add deletion to ring buffer
parent
1a14b811
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
100 additions
and
13 deletions
+100
-13
Lib_TimeboundRingBuffer.sol
...stic-ethereum/libraries/utils/Lib_TimeboundRingBuffer.sol
+54
-7
TestLib_TimeboundRingBuffer.sol
...acts/test-libraries/utils/TestLib_TimeboundRingBuffer.sol
+6
-2
Lib_TimeboundRingBuffer.spec.ts
...contracts/libraries/utils/Lib_TimeboundRingBuffer.spec.ts
+40
-4
No files found.
packages/contracts/contracts/optimistic-ethereum/libraries/utils/Lib_TimeboundRingBuffer.sol
View file @
f6c20be2
...
@@ -9,6 +9,7 @@ struct TimeboundRingBuffer {
...
@@ -9,6 +9,7 @@ struct TimeboundRingBuffer {
bytes32 context;
bytes32 context;
uint32 maxSize;
uint32 maxSize;
uint32 maxSizeIncrementAmount;
uint32 maxSizeIncrementAmount;
uint32 deletionOffset;
uint firstElementTimestamp;
uint firstElementTimestamp;
uint timeout;
uint timeout;
}
}
...
@@ -31,7 +32,7 @@ library Lib_TimeboundRingBuffer {
...
@@ -31,7 +32,7 @@ library Lib_TimeboundRingBuffer {
_self.firstElementTimestamp = block.timestamp;
_self.firstElementTimestamp = block.timestamp;
}
}
function push(
function push
AppendOnly
(
TimeboundRingBuffer storage _self,
TimeboundRingBuffer storage _self,
bytes32 _ele,
bytes32 _ele,
bytes28 _extraData
bytes28 _extraData
...
@@ -50,7 +51,20 @@ library Lib_TimeboundRingBuffer {
...
@@ -50,7 +51,20 @@ library Lib_TimeboundRingBuffer {
_self.context = makeContext(uint32(length+1), _extraData);
_self.context = makeContext(uint32(length+1), _extraData);
}
}
function push2(
function push(
TimeboundRingBuffer storage _self,
bytes32 _ele,
bytes28 _extraData
)
internal
{
pushAppendOnly(_self, _ele, _extraData);
if (_self.deletionOffset != 0) {
_self.deletionOffset += 1;
}
}
function push2AppendOnly(
TimeboundRingBuffer storage _self,
TimeboundRingBuffer storage _self,
bytes32 _ele1,
bytes32 _ele1,
bytes32 _ele2,
bytes32 _ele2,
...
@@ -72,6 +86,20 @@ library Lib_TimeboundRingBuffer {
...
@@ -72,6 +86,20 @@ library Lib_TimeboundRingBuffer {
_self.context = makeContext(uint32(length+2), _extraData);
_self.context = makeContext(uint32(length+2), _extraData);
}
}
function push2(
TimeboundRingBuffer storage _self,
bytes32 _ele1,
bytes32 _ele2,
bytes28 _extraData
)
internal
{
push2AppendOnly(_self, _ele1, _ele2, _extraData);
if (_self.deletionOffset != 0) {
_self.deletionOffset = _self.deletionOffset == 1 ? 0 : _self.deletionOffset - 2;
}
}
function makeContext(
function makeContext(
uint32 _length,
uint32 _length,
bytes28 _extraData
bytes28 _extraData
...
@@ -106,8 +134,8 @@ library Lib_TimeboundRingBuffer {
...
@@ -106,8 +134,8 @@ library Lib_TimeboundRingBuffer {
uint32
uint32
)
)
{
{
bytes32 lengthMask = 0x00000000000000000000000000000000000000000000000000000000ffffffff;
// Length is the last 4 bytes
return uint32(uint256(context &
lengthMask
));
return uint32(uint256(context &
0x00000000000000000000000000000000000000000000000000000000ffffffff
));
}
}
function getExtraData(
function getExtraData(
...
@@ -119,8 +147,8 @@ library Lib_TimeboundRingBuffer {
...
@@ -119,8 +147,8 @@ library Lib_TimeboundRingBuffer {
bytes28
bytes28
)
)
{
{
bytes32 extraDataMask = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000;
// Extra Data is the first 28 bytes
return bytes28(_self.context &
extraDataMask
);
return bytes28(_self.context &
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000
);
}
}
function get(
function get(
...
@@ -135,7 +163,26 @@ library Lib_TimeboundRingBuffer {
...
@@ -135,7 +163,26 @@ library Lib_TimeboundRingBuffer {
{
{
uint length = _getLength(_self.context);
uint length = _getLength(_self.context);
require(_index < length, "Index too large.");
require(_index < length, "Index too large.");
require(length - _index <= _self.maxSize, "Index too old & has been overridden.");
require(length - _index <= _self.maxSize
- _self.deletionOffset
, "Index too old & has been overridden.");
return _self.elements[_index % _self.maxSize];
return _self.elements[_index % _self.maxSize];
}
}
function deleteElementsAfter(
TimeboundRingBuffer storage _self,
uint32 _index,
bytes28 _extraData
)
internal
{
uint32 length = _getLength(_self.context);
uint32 deletionStartingIndex = _index + 1;
uint32 numDeletedElements = length - deletionStartingIndex;
uint32 newDeletionOffset = _self.deletionOffset + numDeletedElements;
require(deletionStartingIndex < length, "Index too large.");
require(newDeletionOffset <= _self.maxSize, "Attempting to delete too many elements.");
_self.deletionOffset = newDeletionOffset;
_self.context = makeContext(deletionStartingIndex, _extraData);
}
}
}
\ No newline at end of file
packages/contracts/contracts/test-libraries/utils/TestLib_TimeboundRingBuffer.sol
View file @
f6c20be2
...
@@ -34,8 +34,12 @@ contract TestLib_TimeboundRingBuffer {
...
@@ -34,8 +34,12 @@ contract TestLib_TimeboundRingBuffer {
list.push2(_ele1, _ele2, _extraData);
list.push2(_ele1, _ele2, _extraData);
}
}
function get(uint32 index) public view returns(bytes32) {
function get(uint32 _index) public view returns(bytes32) {
return list.get(index);
return list.get(_index);
}
function deleteElementsAfter(uint32 _index, bytes28 _extraData) public {
return list.deleteElementsAfter(_index, _extraData);
}
}
function getLength() public view returns(uint32) {
function getLength() public view returns(uint32) {
...
...
packages/contracts/test/contracts/libraries/utils/Lib_TimeboundRingBuffer.spec.ts
View file @
f6c20be2
...
@@ -29,6 +29,8 @@ describe('Lib_TimeboundRingBuffer', () => {
...
@@ -29,6 +29,8 @@ describe('Lib_TimeboundRingBuffer', () => {
let
Lib_TimeboundRingBuffer
:
Contract
let
Lib_TimeboundRingBuffer
:
Contract
const
NON_NULL_BYTES28
=
makeHexString
(
'
01
'
,
28
)
const
NON_NULL_BYTES28
=
makeHexString
(
'
01
'
,
28
)
const
pushNum
=
(
num
:
Number
)
=>
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
num
),
NON_NULL_BYTES28
)
const
push2Nums
=
(
num1
:
Number
,
num2
:
Number
)
=>
Lib_TimeboundRingBuffer
.
push2
(
numToBytes32
(
num1
),
numToBytes32
(
num2
),
NON_NULL_BYTES28
)
describe
(
'
push with no timeout
'
,
()
=>
{
describe
(
'
push with no timeout
'
,
()
=>
{
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
...
@@ -77,7 +79,6 @@ describe('Lib_TimeboundRingBuffer', () => {
...
@@ -77,7 +79,6 @@ describe('Lib_TimeboundRingBuffer', () => {
describe
(
'
push with timeout
'
,
()
=>
{
describe
(
'
push with timeout
'
,
()
=>
{
const
startSize
=
2
const
startSize
=
2
const
pushNum
=
(
num
:
Number
)
=>
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
num
),
NON_NULL_BYTES28
)
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
Lib_TimeboundRingBuffer
=
await
(
Lib_TimeboundRingBuffer
=
await
(
...
@@ -118,15 +119,12 @@ describe('Lib_TimeboundRingBuffer', () => {
...
@@ -118,15 +119,12 @@ describe('Lib_TimeboundRingBuffer', () => {
describe
(
'
push2 with timeout
'
,
()
=>
{
describe
(
'
push2 with timeout
'
,
()
=>
{
const
startSize
=
2
const
startSize
=
2
const
push2Nums
=
(
num1
:
Number
,
num2
:
Number
)
=>
Lib_TimeboundRingBuffer
.
push2
(
numToBytes32
(
num1
),
numToBytes32
(
num2
),
NON_NULL_BYTES28
)
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
Lib_TimeboundRingBuffer
=
await
(
Lib_TimeboundRingBuffer
=
await
(
await
ethers
.
getContractFactory
(
'
TestLib_TimeboundRingBuffer
'
)
await
ethers
.
getContractFactory
(
'
TestLib_TimeboundRingBuffer
'
)
).
deploy
(
startSize
,
1
,
10
_000
)
).
deploy
(
startSize
,
1
,
10
_000
)
})
})
// it('should push two values which extends the array', async () => {
// })
it
(
'
should push a single value which extends the array
'
,
async
()
=>
{
it
(
'
should push a single value which extends the array
'
,
async
()
=>
{
await
push2Nums
(
0
,
1
)
await
push2Nums
(
0
,
1
)
...
@@ -156,4 +154,42 @@ describe('Lib_TimeboundRingBuffer', () => {
...
@@ -156,4 +154,42 @@ describe('Lib_TimeboundRingBuffer', () => {
expect
(
await
Lib_TimeboundRingBuffer
.
getExtraData
()).
to
.
equal
(
NON_NULL_BYTES28
)
expect
(
await
Lib_TimeboundRingBuffer
.
getExtraData
()).
to
.
equal
(
NON_NULL_BYTES28
)
})
})
})
})
describe
(
'
deleteElementsAfter
'
,
()
=>
{
// [0,1,2,3] -> [0,1,-,-]
beforeEach
(
async
()
=>
{
Lib_TimeboundRingBuffer
=
await
(
await
ethers
.
getContractFactory
(
'
TestLib_TimeboundRingBuffer
'
)
).
deploy
(
4
,
1
,
0
)
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
pushNum
(
i
)
}
})
it
(
'
should disallow deletions which are too old
'
,
async
()
=>
{
push2Nums
(
4
,
5
)
await
expect
(
Lib_TimeboundRingBuffer
.
deleteElementsAfter
(
0
,
NON_NULL_BYTES28
)).
to
.
be
.
revertedWith
(
"
Attempting to delete too many elements.
"
)
})
it
(
'
should not allow get to be called on an old value even after deletion
'
,
async
()
=>
{
pushNum
(
4
)
expect
(
await
Lib_TimeboundRingBuffer
.
getMaxSize
()).
to
.
equal
(
4
)
await
expect
(
Lib_TimeboundRingBuffer
.
get
(
0
)).
to
.
be
.
revertedWith
(
"
Index too old & has been overridden.
"
)
Lib_TimeboundRingBuffer
.
deleteElementsAfter
(
3
,
NON_NULL_BYTES28
)
await
expect
(
Lib_TimeboundRingBuffer
.
get
(
0
)).
to
.
be
.
revertedWith
(
"
Index too old & has been overridden.
"
)
await
expect
(
Lib_TimeboundRingBuffer
.
get
(
4
)).
to
.
be
.
revertedWith
(
"
Index too large.
"
)
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
1
)).
to
.
equal
(
numToBytes32
(
1
))
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
3
)).
to
.
equal
(
numToBytes32
(
3
))
})
it
(
'
should not reduce the overall size of the buffer
'
,
async
()
=>
{
pushNum
(
4
)
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
1
)).
to
.
equal
(
numToBytes32
(
1
))
// We expect that we can still access `1` because the deletionOffset
// will have reduced by 1 after we pushed.
Lib_TimeboundRingBuffer
.
deleteElementsAfter
(
3
,
NON_NULL_BYTES28
)
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
1
)).
to
.
equal
(
numToBytes32
(
1
))
})
})
})
})
\ No newline at end of file
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