Skip to content

Commit

Permalink
refactor: Oracles uses Context, beginning refactor to mimic http.List…
Browse files Browse the repository at this point in the history
…en/Parser/Handler
  • Loading branch information
randomshinichi committed Jan 21, 2020
1 parent 6601570 commit 9367aeb
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 26 deletions.
61 changes: 45 additions & 16 deletions aeternity/oracles.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,34 @@ import (
"github.com/aeternity/aepp-sdk-go/v7/transactions"
)

type generateTTLNoncerNodeInterface interface {
naet.GetAccounter
naet.GetHeighter
type oracleQuery string
type oracleResponse string
type oracleResponder interface {
SendOracleResponse(ctx ContextInterface, resp oracleResponse)
}

// CreateOracle registers a new oracle with the given queryspec and responsespec
func (ctx *Context) CreateOracle(queryspec, responsespec string, queryFee *big.Int, queryTTLType uint64, oracleTTL uint64) (oracleID string, err error) {
registerTx, err := transactions.NewOracleRegisterTx(ctx.Account.Address, queryspec, responsespec, queryFee, queryTTLType, oracleTTL, config.Client.Oracles.ABIVersion, ctx.TTLNoncer)
if err != nil {
return
}
type listener func(node oracleInfoer, oracleID string, queryChan chan *models.OracleQuery, errChan chan error, listenInterval time.Duration) (err error)
type handler func(queryStr oracleQuery, respStr oracleResponder)

ctx.SignBroadcastWait(registerTx, config.Client.WaitBlocks)
return registerTx.ID(), nil
type oracleInfoer interface {
naet.GetOracleByPubkeyer
naet.GetOracleQueriesByPubkeyer
}
type Oracle struct {
ID string
node oracleInfoer
ctx ContextInterface
listener listener
}

// ListenOracleQueries polls the node at a custom interval and returns queries
// and errors in their respective channels. listenInterval should be specified
// in milliseconds.
func ListenOracleQueries(n naet.GetOracleQueriesByPubkeyer, oracleID string, queryChan chan *models.OracleQuery, errChan chan error, listenInterval time.Duration) (err error) {
func DefaultOracleListener(node oracleInfoer, oracleID string, queryChan chan *models.OracleQuery, errChan chan error, listenInterval time.Duration) error {
// Node always returns all queries, but keeping track of until where we read
// last iteration ensures we only report newly arriving queries. This means
// the first time this loop runs, it will always return all the queries to
// an oracle.
var readUntilPosition int
for {
oQueries, err := n.GetOracleQueriesByPubkey(oracleID)
oQueries, err := node.GetOracleQueriesByPubkey(oracleID)
if err != nil {
errChan <- err
} else {
Expand All @@ -49,3 +50,31 @@ func ListenOracleQueries(n naet.GetOracleQueriesByPubkeyer, oracleID string, que
time.Sleep(listenInterval * time.Millisecond)
}
}

func NewOracle(node oracleInfoer, ctx ContextInterface, ID string) *Oracle {
return &Oracle{
ID: ID,
ctx: ctx,
node: node,
listener: DefaultOracleListener,
}
}

// CreateOracle registers a new oracle with the given queryspec and responsespec
func (o *Oracle) Register(queryspec, responsespec string, queryFee *big.Int, queryTTLType uint64, oracleTTL uint64) (oracleID string, err error) {
registerTx, err := transactions.NewOracleRegisterTx(o.ctx.SenderAccount(), queryspec, responsespec, queryFee, queryTTLType, oracleTTL, config.Client.Oracles.ABIVersion, o.ctx.TTLNoncer())
if err != nil {
return
}

o.ctx.SignBroadcastWait(registerTx, config.Client.WaitBlocks)
return registerTx.ID(), nil
}

func (o *Oracle) Listen() error {
_, err := o.node.GetOracleByPubkey(o.ID)
if err != nil { // How can we find out through the error that the oracle does not exist/404?
return err
}
return nil
}
24 changes: 14 additions & 10 deletions aeternity/oracles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@ func newMockOracleQueryNode() *mockOracleQueryNode {
},
}
}
func (m *mockOracleQueryNode) GetOracleByPubkey(pubkey string) (oracleQueries *models.RegisteredOracle, err error) {
return &models.RegisteredOracle{}, err
}

func (m *mockOracleQueryNode) GetOracleQueriesByPubkey(pubkey string) (oracleQueries *models.OracleQueries, err error) {
return m.oracleQueries, err
}
func newOracleQuery(i int) (q *models.OracleQuery, err error) {
q = new(models.OracleQuery)
qJSON := fmt.Sprintf(`{"fee":%d,"id":"oq_FAKEQUERY","oracle_id":"ok_FAKEID","query":"ov_FAKEQUERY=","response":"or_FAKERESPONSE","response_ttl":{"type":"delta","value":100},"sender_id":"ak_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi","sender_nonce":%d,"ttl":137}`, i, i)
err = q.UnmarshalBinary([]byte(qJSON))
return
}

func (m *mockOracleQueryNode) AddOracleQuery(n int) (err error) {
var newOracleQuery = func(i int) (q *models.OracleQuery, err error) {
q = new(models.OracleQuery)
qJSON := fmt.Sprintf(`{"fee":%d,"id":"oq_FAKEQUERY","oracle_id":"ok_FAKEID","query":"ov_FAKEQUERY=","response":"or_FAKERESPONSE","response_ttl":{"type":"delta","value":100},"sender_id":"ak_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi","sender_nonce":%d,"ttl":137}`, i, i)
err = q.UnmarshalBinary([]byte(qJSON))
return
}
// Create some fake OracleQuerys to add them to
// mockOracleQueryNode.OracleQueries. Keep track of how many we have
// created.
Expand All @@ -45,12 +49,12 @@ func (m *mockOracleQueryNode) AddOracleQuery(n int) (err error) {
return
}

func TestListenOracleQueries(t *testing.T) {
func TestDefaultOracleListener(t *testing.T) {
n := newMockOracleQueryNode()

oQueries := make(chan *models.OracleQuery, 30)
errChan := make(chan error)
go ListenOracleQueries(n, "ok_FAKEID", oQueries, errChan, 20)
go DefaultOracleListener(n, "ok_FAKEID", oQueries, errChan, 20)
n.AddOracleQuery(3)
n.AddOracleQuery(5)
time.Sleep(20 * time.Millisecond)
Expand All @@ -62,15 +66,15 @@ func TestListenOracleQueries(t *testing.T) {
}
}

func TestManyPendingOracleQueries(t *testing.T) {
func TestDefaultOracleListenerManyPendingQueries(t *testing.T) {
n := newMockOracleQueryNode()
readQueries := []*models.OracleQuery{}
oQueries := make(chan *models.OracleQuery, 5)
errChan := make(chan error)

n.AddOracleQuery(100)

go ListenOracleQueries(n, "ok_FAKEID", oQueries, errChan, 20)
go DefaultOracleListener(n, "ok_FAKEID", oQueries, errChan, 20)

var q *models.OracleQuery
for i := 0; i < 100; i++ {
Expand Down

0 comments on commit 9367aeb

Please sign in to comment.