0

I wrote a contract source which is just a FIFO queue below:

pragma solidity ^0.4.0;
contract queue
{
    struct Queue {
        uint256[] data;
        uint256 front;
        uint256 back;
    }
    /// @dev the number of elements stored in the queue.
    function length(Queue storage q) constant internal returns (uint256) {
        return q.back - q.front;
    }
    /// @dev the number of elements this queue can hold
    function capacity(Queue storage q) constant internal returns (uint256) {
        return q.data.length - 1;
    }
    /// @dev push a new element to the back of the queue
    function push(Queue storage q, uint256 data) internal
    {
        if ((q.back + 1) % q.data.length == q.front)
            return; // throw;
        q.data[q.back] = data;
        q.back = (q.back + 1) % q.data.length;
    }
    /// @dev remove and return the element at the front of the queue
    function pop(Queue storage q) internal returns (uint256 r)
    {
        if (q.back == q.front)
            return; // throw;
        r = q.data[q.front];
        delete q.data[q.front];
        q.front = (q.front + 1) % q.data.length;
        return r;
    }
    Queue requests;
    function queue() {
        requests.data.length = 200;
    }
    function addRequest(uint256 d) {
        push(requests, d);
    }
    function popRequest() constant returns (uint256) {
        return pop(requests);
    }
    function queueLength()  constant returns (uint256) {
        return length(requests);
    }
    function hello() constant returns(string s){ 
        return 'hello world!';
    }
}

and then I compile it on online compiler https://ethereum.github.io/browser-solidity. I got the contents from the Web3 deploy box, which is :

var queue_sol_queueContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"hello","outputs":[{"name":"s","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"d","type":"uint256"}],"name":"addRequest","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"queueLength","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"popRequest","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}]);
var queue_sol_queue = queue_sol_queueContract.new(
   {
     from: web3.eth.accounts[0], 
     data: '0x6060604052341561000c57fe5b5b60c860006000018161001f9190610026565b505b610077565b81548183558181151161004d5781836000526020600020918201910161004c9190610052565b5b505050565b61007491905b80821115610070576000816000905550600101610058565b5090565b90565b610339806100866000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806319ff1d211461005c5780634ca1fad8146100f5578063ab91c7b014610115578063e4690a0b1461013b575bfe5b341561006457fe5b61006c610161565b60405180806020018281038252838181518152602001915080519060200190808383600083146100bb575b8051825260208311156100bb57602082019150602081019050602083039250610097565b505050905090810190601f1680156100e75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100fd57fe5b61011360048080359060200190919050506101a6565b005b341561011d57fe5b6101256101b5565b6040518082815260200191505060405180910390f35b341561014357fe5b61014b6101c7565b6040518082815260200191505060405180910390f35b6101696102f9565b604060405190810160405280600c81526020017f68656c6c6f20776f726c6421000000000000000000000000000000000000000081525090505b90565b6101b16000826101d9565b5b50565b60006101c16000610253565b90505b90565b60006101d36000610268565b90505b90565b8160010154826000018054905060018460020154018115156101f757fe5b0614156102035761024f565b8082600001836002015481548110151561021957fe5b906000526020600020900160005b50819055508160000180549050600183600201540181151561024557fe5b0682600201819055505b5050565b6000816001015482600201540390505b919050565b600081600101548260020154141561027f576102f4565b81600001826001015481548110151561029457fe5b906000526020600020900160005b505490508160000182600101548154811015156102bb57fe5b906000526020600020900160005b5060009055816000018054905060018360010154018115156102e757fe5b0682600101819055508090505b919050565b6020604051908101604052806000815250905600a165627a7a7230582052aa3a94b7e1e757a3b8de91244871650c0e29a8114a06384386ab323fae210e0029', 
     gas: '800000'
   }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
         console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
 })

Ok, I click the create button to test it and it works well. Then I deploy it on my geth but its response isn't good enough:

> eth.defaultAccount = eth.accounts[0]
"0x047347096a6dc73f8626afb520c383a02efda314"
> queue_sol_queue.addRequest(2)
I0405 16:19:43.308834 internal/ethapi/api.go:1076] Tx(0xc42776310dde4eb79798ba02f33176bcbb0a8283aa3bb4508af0fd30ed34175e) to: 0x1666d22ba16ff64f94d938301f8ec252f88813a3
"0xc42776310dde4eb79798ba02f33176bcbb0a8283aa3bb4508af0fd30ed34175e"
> queue_sol_queue.addRequest.call(2)
[]
> queue_sol_queue.addRequest.call(2)
[]
> queue_sol_queue.addRequest.call(2)
[]
> queue_sol_queue.popRequest()
0
> queue_sol_queue.popRequest.call()
0

it seems that the push can't push any data and pop can't pop any data ,So how do it work like a FIFO queue? thank you very much.

After getting help from some nice people. I have a new question here: How to return the value pushed before with only one function? I read some information about events, so I think it may be a solution, but it doesn't return the exact value pushed before. There is my new source below which added events:

pragma solidity ^0.4.0;
////////////////////////////////////////////////////////////
// This is an example contract hacked together at a meetup.
// It is by far not complete and only used to show some
// features of Solidity.
////////////////////////////////////////////////////////////
contract queue
{
    struct Queue {
        uint256[] data;
        uint256 front;
        uint256 back;
    }
    /// @dev the number of elements stored in the queue.
    function length(Queue storage q) constant internal returns (uint256) {
        return q.back - q.front;
    }
    /// @dev the number of elements this queue can hold
    function capacity(Queue storage q) constant internal returns (uint256) {
        return q.data.length - 1;
    }
    /// @dev push a new element to the back of the queue
    function push(Queue storage q, uint256 data) internal
    {
        if ((q.back + 1) % q.data.length == q.front)
            return; // throw;
        q.data[q.back] = data;
        q.back = (q.back + 1) % q.data.length;
    }


    /// @dev remove and return the element at the front of the queue
    function pop(Queue storage q) internal returns (uint256 r)
    {
        if (q.back == q.front)
            return; // throw;
        r = q.data[q.front];
        delete q.data[q.front];
        q.front = (q.front + 1) % q.data.length;
        return r;
    }
    Queue requests;
    event PopEvent(bool ok); //my event designed by me here.(*^__^*) 嘻嘻……
    function queue() {
        requests.data.length = 200;
    }
    function addRequest(uint256 d) {
        push(requests, d);
    }
    function popRequest()  returns (uint256) {
        PopEvent(true);
        return pop(requests);
    }
    function queueLength()  constant returns (uint256) {
        return length(requests);
    }
    function hello() constant returns(string s){ 
        return 'hello world!';
    }
}

Hence, can any body help me? thank you!!!

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
jiebang
  • 993
  • 1
  • 12
  • 18

2 Answers2

1

Regarding addRequest: in web3 console, the function call should also specify the from argument to tell which account to use for authorizing the trasaction:

> queue_sol_queue.addRequest(2, { from: web3.eth.accounts[0] })

Regarding the popRequest: since there is state change for popping the element out of the queue, the function should not be constant. You can remove it and try again.

Yuanfei Zhu
  • 578
  • 4
  • 16
  • queue_sol_queue.addRequest(2, { from: web3.eth.accounts[0] })

    I0405 17:20:58.392193 internal/ethapi/api.go:1076] Tx(0xa4d56e43de8f9378493ea4c8ce2f7bb9db4d975a8d7823288ea0c4894299393b) to: 0xc8cf1ea4b0287d559078ad47e12dcc94dd699431 "0xa4d56e43de8f9378493ea4c8ce2f7bb9db4d975a8d7823288ea0c4894299393b"

    queue_sol_queue.popRequest()

    I0405 17:22:36.338967 internal/ethapi/api.go:1076] Tx(0x94ed63dbd0b1dd4ff5b6d0a881602b322d517e746c40e197af641dafe517fac6) to: 0xc8cf1ea4b0287d559078ad47e12dcc94dd699431 "0x94ed63dbd0b1dd4ff5b6d0a881602b322d517e746c40e197af641dafe517fac6" is it works well?

    – jiebang Apr 05 '17 at 09:23
  • And what is the return value like : queue_sol_queue.addRequest(2, { from: web3.eth.accounts[0] }) I0405 17:20:58.392193 internal/ethapi/api.go:1076] Tx(0xa4d56e43de8f9378493ea4c8ce2f7bb9db4d975a8d7823288ea0c4894299393b) to: 0xc8cf1ea4b0287d559078ad47e12dcc94dd699431 "0xa4d56e43de8f9378493ea4c8ce2f7bb9db4d975a8d7823288ea0c4894299393b" – jiebang Apr 05 '17 at 09:25
  • It seems to be OK, you can check the queueLength() to confirm it works. The return value is the transaction address for this function call. – Yuanfei Zhu Apr 05 '17 at 09:53
  • Thank you very much .but I want to it return the exact value such as popRequest() return the value which is pushed before. How can it do like that ? – jiebang Apr 05 '17 at 11:47
  • Check this answer about the difference between transaction and function calls. – Yuanfei Zhu Apr 05 '17 at 12:14
  • Can I ask what the purpose is of the modulo operator % q.data.length in the likes of q.back = (q.back + 1) % q.data.length;? – o0ragman0o Apr 05 '17 at 13:00
  • That's to model a rotated queue which assumes the elements in queue is always less than the size of the queue so that the space occupied by the front elements can be reused safely. – Yuanfei Zhu Apr 05 '17 at 16:56
  • thank you for your help. But I want to just only one function to return the value. So what is the solution? I use event in my source, but it doesn't work now. – jiebang Apr 06 '17 at 08:36
  • Can you create a separate new question with more descriptive details? Thank you! – Yuanfei Zhu Apr 06 '17 at 08:39
  • I have updated my question here. please help me.thank you. – jiebang Apr 06 '17 at 08:44
  • I mean to create a new question with more specific issue you'd like to address... – Yuanfei Zhu Apr 06 '17 at 08:45
  • OK, i have created a new question named How to return a exact value pushed before in my contract? – jiebang Apr 06 '17 at 08:55
  • I have a new question here:http://ethereum.stackexchange.com/questions/15076/event-watcher-gives-object-object-in-geth-console, may be you could help me.thanks. – jiebang Apr 10 '17 at 13:21
  • Hi, I have a question here: I can use queue_sol_queue.addRequest(2, { from: web3.eth.accounts[0] }) to add the data of 2 to the queue. But where is the 2 stored? is the 2 stored to the blockchain? thank you . – jiebang Apr 20 '17 at 06:31
  • Yes, it's persist on chain. – Yuanfei Zhu Apr 21 '17 at 07:32
0

As for returning values, you could have a constant function to read followed by the pop to clear it out. function getFront() public constant returns (uint) { return request.data[front];}

From web3.js you can set up a batch request to call getFront() and pop() in sequence.

o0ragman0o
  • 4,320
  • 18
  • 35
  • thank you for your help. But I want to just only one function to return the value. So what is the solution? I use event in my source, but it doesn't work now. – jiebang Apr 06 '17 at 08:36