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
3ec7c358
Commit
3ec7c358
authored
Oct 11, 2020
by
Karl Floersch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement first pass of ring buffer
parent
51e6bbbb
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
260 additions
and
0 deletions
+260
-0
Lib_TimeboundRingBuffer.sol
...stic-ethereum/libraries/utils/Lib_TimeboundRingBuffer.sol
+105
-0
TestLib_TimeboundRingBuffer.sol
...acts/test-libraries/utils/TestLib_TimeboundRingBuffer.sol
+56
-0
Lib_TimeboundRingBuffer.spec.ts
...contracts/libraries/utils/Lib_TimeboundRingBuffer.spec.ts
+99
-0
No files found.
packages/contracts/contracts/optimistic-ethereum/libraries/utils/Lib_TimeboundRingBuffer.sol
0 → 100644
View file @
3ec7c358
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
/* Logging */
import { console } from "@nomiclabs/buidler/console.sol";
struct TimeboundRingBuffer {
mapping(uint=>bytes32) elements;
bytes32 context;
uint32 maxSize;
uint32 maxSizeIncrementAmount;
uint firstElementTimestamp;
uint timeout;
}
/**
* @title Lib_TimeboundRingBuffer
*/
library Lib_TimeboundRingBuffer {
function init(
TimeboundRingBuffer storage _self,
uint32 _startingSize,
uint32 _maxSizeIncrementAmount,
uint _timeout
)
internal
{
_self.maxSize = _startingSize;
_self.maxSizeIncrementAmount = _maxSizeIncrementAmount;
_self.timeout = _timeout;
_self.firstElementTimestamp = block.timestamp;
}
function push(
TimeboundRingBuffer storage _self,
bytes32 _ele,
bytes28 _extraData
)
internal
{
uint length = _getLength(_self.context);
uint maxSize = _self.maxSize;
if (length == maxSize) {
if (block.timestamp < _self.firstElementTimestamp + _self.timeout) {
_self.maxSize += _self.maxSizeIncrementAmount;
maxSize = _self.maxSize;
}
}
_self.elements[length % maxSize] = _ele;
_self.context = makeContext(uint32(length+1), _extraData);
}
function makeContext(
uint32 _length,
bytes28 _extraData
)
internal
pure
returns(
bytes32
)
{
return bytes32(bytes4(_length));
}
function getLength(
TimeboundRingBuffer storage _self
)
internal
view
returns(
uint32
)
{
return _getLength(_self.context);
}
function _getLength(
bytes32 context
)
internal
pure
returns(
uint32
)
{
return uint32(bytes4(context));
}
function get(
TimeboundRingBuffer storage _self,
uint32 _index
)
internal
view
returns(
bytes32
)
{
uint length = _getLength(_self.context);
require(_index < length, "Index too large.");
require(length - _index <= _self.maxSize, "Index too old & has been overridden.");
return _self.elements[_index % _self.maxSize];
}
}
\ No newline at end of file
packages/contracts/contracts/test-libraries/utils/TestLib_TimeboundRingBuffer.sol
0 → 100644
View file @
3ec7c358
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
/* Logging */
import { console } from "@nomiclabs/buidler/console.sol";
/* Library Imports */
import { TimeboundRingBuffer, Lib_TimeboundRingBuffer } from "../../optimistic-ethereum/libraries/utils/Lib_TimeboundRingBuffer.sol";
/**
* @title TestLib_TimeboundRingBuffer
*/
contract TestLib_TimeboundRingBuffer {
using Lib_TimeboundRingBuffer for TimeboundRingBuffer;
TimeboundRingBuffer public list;
constructor (
uint32 _startingSize,
uint32 _maxSizeIncrementAmount,
uint _timeout
)
public
{
list.init(_startingSize, _maxSizeIncrementAmount, _timeout);
}
function push(bytes32 _ele, bytes28 _extraData) public {
list.push(_ele, _extraData);
}
function get(uint32 index) public view returns(bytes32) {
return list.get(index);
}
function getLength() public view returns(uint32) {
return list.getLength();
}
function getMaxSize() public view returns(uint32) {
return list.maxSize;
}
function getMaxSizeIncrementAmount() public view returns(uint32) {
return list.maxSizeIncrementAmount;
}
function getFirstElementTimestamp() public view returns(uint) {
return list.firstElementTimestamp;
}
function getTimeout() public view returns(uint) {
return list.timeout;
}
}
\ No newline at end of file
packages/contracts/test/contracts/libraries/utils/Lib_TimeboundRingBuffer.spec.ts
0 → 100644
View file @
3ec7c358
/* tslint:disable:no-empty */
import
{
expect
}
from
'
../../../setup
'
/* External Imports */
import
{
ethers
}
from
'
@nomiclabs/buidler
'
import
{
Contract
,
Signer
}
from
'
ethers
'
/* Internal Imports */
import
{
NON_NULL_BYTES32
,
makeHexString
,
fromHexString
,
getHexSlice
,
increaseEthTime
}
from
'
../../../helpers
'
const
numToBytes32
=
(
num
:
Number
)
=>
{
if
(
num
<
0
||
num
>
255
)
{
throw
new
Error
(
'
Unsupported number.
'
)
}
const
strNum
=
(
num
<
16
)
?
'
0
'
+
num
.
toString
(
16
)
:
num
.
toString
(
16
)
return
'
0x
'
+
'
00
'
.
repeat
(
31
)
+
strNum
}
describe
.
only
(
'
Lib_TimeboundRingBuffer
'
,
()
=>
{
let
signer
:
Signer
before
(
async
()
=>
{
;[
signer
]
=
await
ethers
.
getSigners
()
})
let
Lib_TimeboundRingBuffer
:
Contract
const
NON_NULL_BYTES28
=
makeHexString
(
'
01
'
,
28
)
describe
(
'
[0,1,2,3] with no timeout
'
,
()
=>
{
beforeEach
(
async
()
=>
{
Lib_TimeboundRingBuffer
=
await
(
await
ethers
.
getContractFactory
(
'
TestLib_TimeboundRingBuffer
'
)
).
deploy
(
4
,
1
,
0
)
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
await
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
i
),
NON_NULL_BYTES28
)
}
})
it
(
'
should push a single value which increases the length
'
,
async
()
=>
{
expect
(
await
Lib_TimeboundRingBuffer
.
getLength
()).
to
.
equal
(
4
)
await
Lib_TimeboundRingBuffer
.
push
(
NON_NULL_BYTES32
,
NON_NULL_BYTES28
)
expect
(
await
Lib_TimeboundRingBuffer
.
getLength
()).
to
.
equal
(
5
)
})
it
(
'
should overwrite old values:[0,1,2,3] -> [4,5,2,3]
'
,
async
()
=>
{
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
0
)).
to
.
equal
(
numToBytes32
(
0
))
await
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
4
),
NON_NULL_BYTES28
)
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
4
)).
to
.
equal
(
numToBytes32
(
4
))
await
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
5
),
NON_NULL_BYTES28
)
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
5
)).
to
.
equal
(
numToBytes32
(
5
))
})
})
describe
(
'
push with timeout
'
,
()
=>
{
const
startSize
=
2
beforeEach
(
async
()
=>
{
Lib_TimeboundRingBuffer
=
await
(
await
ethers
.
getContractFactory
(
'
TestLib_TimeboundRingBuffer
'
)
).
deploy
(
startSize
,
1
,
10
_000
)
for
(
let
i
=
0
;
i
<
startSize
;
i
++
)
{
await
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
i
),
NON_NULL_BYTES28
)
}
})
const
pushNum
=
(
num
:
Number
)
=>
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
num
),
NON_NULL_BYTES28
)
const
pushJunk
=
()
=>
Lib_TimeboundRingBuffer
.
push
(
NON_NULL_BYTES32
,
NON_NULL_BYTES28
)
it
(
'
should push a single value which extends the array
'
,
async
()
=>
{
await
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
2
),
NON_NULL_BYTES28
)
const
increasedSize
=
startSize
+
1
expect
(
await
Lib_TimeboundRingBuffer
.
getMaxSize
()).
to
.
equal
(
increasedSize
)
await
increaseEthTime
(
ethers
.
provider
,
20
_000
)
await
Lib_TimeboundRingBuffer
.
push
(
numToBytes32
(
3
),
NON_NULL_BYTES28
)
expect
(
await
Lib_TimeboundRingBuffer
.
getMaxSize
()).
to
.
equal
(
increasedSize
)
// Shouldn't increase the size this time
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
2
)).
to
.
equal
(
numToBytes32
(
2
))
expect
(
await
Lib_TimeboundRingBuffer
.
get
(
3
)).
to
.
equal
(
numToBytes32
(
3
))
})
it
(
'
should NOT extend the array if the time is not up and extend it when it is
'
,
async
()
=>
{
await
pushJunk
()
const
increasedSize
=
startSize
+
1
expect
(
await
Lib_TimeboundRingBuffer
.
getMaxSize
()).
to
.
equal
(
increasedSize
)
await
increaseEthTime
(
ethers
.
provider
,
20
_000
)
// Push the time forward and verify that the time doesn't increment
for
(
let
i
=
0
;
i
<
increasedSize
+
1
;
i
++
)
{
await
pushJunk
()
}
expect
(
await
Lib_TimeboundRingBuffer
.
getMaxSize
()).
to
.
equal
(
increasedSize
)
})
})
})
\ 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