Skip to content

Commit b475b71

Browse files
astaphobiasukrawidhyawanandy-shi88
authored
Expire musig pending transaction (#828)
* ignore .bak like genesis.go.bak :) * expiring pending transactions by height and undo apply unconfirmed * update readme about multis sig generator * not allow filter by pending and expired * finish query logic to, so now (block_height+min_rollback) = current_block_height * defer func for rows close and matches the others about query logic * add log instance into transaction core service, ignore log level Co-authored-by: Gede Sukra Widhyawan <[email protected]> Co-authored-by: Andy Shi <[email protected]>
1 parent e391d9c commit b475b71

13 files changed

+328
-47
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,6 @@ accounts.txt
2525
.editorconfig
2626
.manual
2727
release/
28-
github.token
28+
github.token
29+
*.back
30+
*.bak

api/handler/multisigHandler.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@ package handler
33
import (
44
"context"
55

6-
"google.golang.org/grpc/codes"
7-
"google.golang.org/grpc/status"
8-
96
"github.com/zoobc/zoobc-core/api/service"
10-
117
"github.com/zoobc/zoobc-core/common/model"
8+
"google.golang.org/grpc/codes"
9+
"google.golang.org/grpc/status"
1210
)
1311

1412
type (
@@ -28,8 +26,8 @@ func (msh *MultisigHandler) GetPendingTransactions(
2826
req.Pagination.OrderField = "block_height"
2927
req.Pagination.OrderBy = model.OrderBy_DESC
3028
}
31-
result, err := msh.MultisigService.GetPendingTransactions(req)
32-
return result, err
29+
30+
return msh.MultisigService.GetPendingTransactions(req)
3331
}
3432

3533
func (msh *MultisigHandler) GetPendingTransactionDetailByTransactionHash(

cmd/block/blockGenerator.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,13 @@ func initialize(
186186
receiptUtil,
187187
publishedReceiptUtil,
188188
service.NewTransactionCoreService(
189+
nil,
189190
queryExecutor,
191+
nil,
192+
nil,
190193
query.NewTransactionQuery(chainType),
191194
nil,
195+
nil,
192196
),
193197
nil,
194198
nil,

cmd/readme.md

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ Command line interface to as a utility tools to develop the zoobc system.
2222
- `go run main {command} --help` to see to see available subcommands and flags
2323
- `go run main {command} {subcommand} --help` to see to see available subcommands and flags of subcommand
2424

25+
## Transaction Commands
2526
### Transaction general flag
2627

2728
- `--output` to provide generated ouput type. Example: `--ouput bytes`
2829
- `--version` to provide version of transaction. Example: `--version 1`
2930
- `--timestamp` to provide timestamp of trasaction. Example: `--timestamp 1234567`
3031
- `--sender-seed` to provide the seed of sender transaction. Example: `--sender-seed "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved"`
32+
- `--sender-address` transaction's sender address
3133
- `--recipient` provide recepient transaction. Example `--recipient VZvYd80p5S-rxSNQmMZwYXC7LyAzBmcfcj4MUUAdudWM`
3234
- `--fee` to provide fee transaction, Example `--fee 1`
3335
- `--post` to define automate post transaction or not. Example: `-post true`
@@ -40,7 +42,7 @@ Command line interface to as a utility tools to develop the zoobc system.
4042
go run main.go generate transaction send-money --timestamp 1257894000 --sender-seed "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved" --recipient VZvYd80p5S-rxSNQmMZwYXC7LyAzBmcfcj4MUUAdudWM --amount 5000000000
4143
```
4244

43-
#### Transaction send money escrow, set flag `--escrow true` and 3 more fields: `--approver-address`, `--timeout`, `--commission` and `--instruction`
45+
### Transaction send money escrow, set flag `--escrow true` and 3 more fields: `--approver-address`, `--timeout`, `--commission` and `--instruction`
4446

4547
```bash
4648
go run main.go generate transaction send-money --escrow true --approver-address BCZEGOb3WNx3fDOVf9ZS4EjvOIv_UeW4TVBQJ_6tHKlE --timeout 200 --sender-seed "execute beach inflict session course dance vanish cover lawsuit earth casino fringe waste warfare also habit skull donate window cannon scene salute dawn good" --amount 1111 --commission 111 --instruction "Check amount should be 111" --recipient nK_ouxdDDwuJiogiDAi_zs1LqeN7f5ZsXbFtXGqGc0Pd
@@ -88,12 +90,34 @@ go run main.go generate transaction remove-account-dataset --timestamp 125789400
8890
go run main.go generate transaction escrow-approval --transaction-id -2546596465476625657 --approval true --sender-seed "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved" --fee 111
8991
```
9092

93+
### Transaction Multi Signatures
94+
```bash
95+
Flags:
96+
--address-signatures stringToString address:signature list --address1='signature1' --address2='signature2' (default [])
97+
--addresses strings list of participants --addresses='address1,address2'
98+
-h, --help help for multi-signature
99+
--min-signature uint32 minimum number of signature required for the transaction to be valid
100+
--nonce int random number / access code for the multisig info
101+
--transaction-hash string hash of transaction being signed by address-signature list hex
102+
--unsigned-transaction string hex string of the unsigned transaction bytes
103+
```
104+
For the multi signature transaction let say want to send money with multisig account, need to do this steps:
105+
1. Generate transaction send money, make sure with argument `--hash`. It will be `--unsigned-transaction` value on multi signature generator.
106+
2. Sign the transaction to get the transaction hash, and it will be `--transcation-has` and the last the `signature-hex` will be as `--address-signatures` value on multi signature generator. <br>
107+
108+
So the completed comment it will be:
109+
```bash
110+
go run main.go generate transaction multi-signature --sender-seed="execute beach inflict session course dance vanish cover lawsuit earth casino fringe waste warfare also habit skull donate window cannon scene salute dawn good" --unsigned-transaction="01000000012ba5ba5e000000002c000000486c5a4c683356636e4e6c764279576f417a584f51326a416c77464f69794f395f6e6a49336f7135596768612c000000486c38393154655446784767574f57664f4f464b59725f586468584e784f384a4b38576e4d4a56366738614c41420f0000000000080000000600000000000000000000000000000000000000000000000000000000000000" --transaction-hash="21ddbdada9903da81bf17dba6569ff7e2665fec38760c7f6636419ee30da65b0" --address-signatures="HlZLh3VcnNlvByWoAzXOQ2jAlwFOiyO9_njI3oq5Ygha=00000000b4efe21822c9d63818d8d19f6c608d917b2237426d1157b4e6689b22ce6c256ccf8ec8e2c1016ab09dd4ef2b01191fe2df70b7a123fec7115d7afd5a938f9b0a"
111+
```
112+
113+
## Block Commands
91114
### Block Generating Fake Blocks
92115

93116
```bash
94117
go run main.go generate block fake-blocks --numberOfBlocks=1000 --blocksmithSecretPhrase='sprinkled sneak species pork outpost thrift unwind cheesy vexingly dizzy neurology neatness' --out='../resource/zoobc.db'
95118
```
96119

120+
## Account Commands
97121
### Account Generate Using Ed25519 Algorithm
98122

99123
```bash
@@ -114,30 +138,28 @@ go run main.go generate account bitcoin --seed "concur vocalist rotten busload g
114138
go run main.go generate account multisig --addresses "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgtN" --addresses "BCZD_VxfO2S9aziIL3cn_cXW7uPDVPOrnXuP98GEAUC7" --addresses "BCZKLvgUYZ1KKx-jtF9KoJskjVPvB9jpIjfzzI6zDW0J" —-min-sigs=2 --nonce=3
115139
```
116140

141+
## Other Commands
142+
```bash
117143
go run main.go genesis generate
144+
```
118145
outputs cmd/genesis.go.new and cmd/cluster_config.json
119146

120147
```bash
121-
122148
### Genesis Generate From cmd/genesisblock/preRegisteredNodes.json and resource/zoobc.db
123149

124150
```
125-
151+
```bash
126152
go run main.go genesis generate -w
153+
```
127154
outputs cmd/genesis.go.new and cmd/cluster_config.json
128155

129-
```bash
130-
131-
### Genesis Generate From cmd/genesisblock/preRegisteredNodes.json and resource/zoobc.db, plus n random nodes registrations
132156

133-
```
134157

158+
### Genesis Generate From cmd/genesisblock/preRegisteredNodes.json and resource/zoobc.db, plus n random nodes registrations
159+
```bash
135160
go run main.go genesis generate -w -n 10
136-
outputs cmd/genesis.go.new and cmd/cluster_config.json
137-
138-
```
139-
140161
```
162+
outputs cmd/genesis.go.new and cmd/cluster_config.json
141163

142164
### Generate Proof of Ownership Node Registry
143165

common/query/multisignatureInfoQuery.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (msi *MultisignatureInfoQuery) GetMultisignatureInfoByAddress(
6363
}
6464
}
6565

66-
// InsertPendingSignature inserts a new pending transaction into DB
66+
// InsertMultisignatureInfo inserts a new pending transaction into DB
6767
func (msi *MultisignatureInfoQuery) InsertMultisignatureInfo(multisigInfo *model.MultiSignatureInfo) [][]interface{} {
6868
var queries [][]interface{}
6969
insertQuery := fmt.Sprintf("INSERT OR REPLACE INTO %s (%s) VALUES(%s)",

common/query/pendingTransactionQuery.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"strings"
77

8+
"github.com/zoobc/zoobc-core/common/constant"
9+
810
"github.com/zoobc/zoobc-core/common/model"
911
)
1012

@@ -22,6 +24,7 @@ type (
2224
) (
2325
str string, args []interface{},
2426
)
27+
GetPendingTransactionsExpireByHeight(blockHeight uint32) (str string, args []interface{})
2528
InsertPendingTransaction(pendingTx *model.PendingTransaction) [][]interface{}
2629
Scan(pendingTx *model.PendingTransaction, row *sql.Row) error
2730
ExtractModel(pendingTx *model.PendingTransaction) []interface{}
@@ -103,6 +106,20 @@ func (ptq *PendingTransactionQuery) GetPendingTransactionsBySenderAddress(
103106
}
104107
}
105108

109+
// GetPendingTransactionsExpireByHeight presents query to get pending_transactions that was expire by block_height
110+
func (ptq *PendingTransactionQuery) GetPendingTransactionsExpireByHeight(currentHeight uint32) (str string, args []interface{}) {
111+
return fmt.Sprintf(
112+
"SELECT %s FROM %s WHERE block_height = ? AND status = ? AND latest = ?",
113+
strings.Join(ptq.Fields, ", "),
114+
ptq.getTableName(),
115+
),
116+
[]interface{}{
117+
currentHeight - constant.MinRollbackBlocks,
118+
model.PendingTransactionStatus_PendingTransactionPending,
119+
true,
120+
}
121+
}
122+
106123
// InsertPendingTransaction inserts a new pending transaction into DB
107124
func (ptq *PendingTransactionQuery) InsertPendingTransaction(pendingTx *model.PendingTransaction) [][]interface{} {
108125
var queries [][]interface{}

common/query/pendingTransactionQuery_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,3 +567,51 @@ func TestPendingTransactionQuery_TrimDataBeforeSnapshot(t *testing.T) {
567567
})
568568
}
569569
}
570+
571+
func TestPendingTransactionQuery_GetPendingTransactionsExpireByHeight(t *testing.T) {
572+
type fields struct {
573+
Fields []string
574+
TableName string
575+
}
576+
type args struct {
577+
currentHeight uint32
578+
}
579+
tests := []struct {
580+
name string
581+
fields fields
582+
args args
583+
wantStr string
584+
wantArgs []interface{}
585+
}{
586+
{
587+
name: "WantSuccess",
588+
fields: fields(*NewPendingTransactionQuery()),
589+
args: args{
590+
currentHeight: 1000,
591+
},
592+
wantStr: "SELECT sender_address, transaction_hash, transaction_bytes, status, block_height, latest " +
593+
"FROM pending_transaction WHERE block_height = ? AND status = ? AND latest = ?",
594+
wantArgs: []interface{}{
595+
uint32(1000) - constant.MinRollbackBlocks,
596+
model.PendingTransactionStatus_PendingTransactionPending,
597+
true,
598+
},
599+
},
600+
}
601+
for _, tt := range tests {
602+
t.Run(tt.name, func(t *testing.T) {
603+
ptq := &PendingTransactionQuery{
604+
Fields: tt.fields.Fields,
605+
TableName: tt.fields.TableName,
606+
}
607+
gotStr, gotArgs := ptq.GetPendingTransactionsExpireByHeight(tt.args.currentHeight)
608+
if gotStr != tt.wantStr {
609+
t.Errorf("GetPendingTransactionsExpireByHeight() gotStr = %v, want %v", gotStr, tt.wantStr)
610+
return
611+
}
612+
if !reflect.DeepEqual(gotArgs, tt.wantArgs) {
613+
t.Errorf("GetPendingTransactionsExpireByHeight() gotArgs = %v, want %v", gotArgs, tt.wantArgs)
614+
}
615+
})
616+
}
617+
}

core/service/blockMainService.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,11 +408,18 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block, broadcast,
408408
return err
409409
}
410410

411-
// Respecting Expiring escrow before push block process
411+
/*
412+
Expiring Process: expiring the the transactions that affected by current block height.
413+
Respecting Expiring escrow and multi signature transaction before push block process
414+
*/
412415
err = bs.TransactionCoreService.ExpiringEscrowTransactions(block.GetHeight(), true)
413416
if err != nil {
414417
return blocker.NewBlocker(blocker.BlockErr, err.Error())
415418
}
419+
err = bs.TransactionCoreService.ExpiringPendingTransactions(block.GetHeight(), true)
420+
if err != nil {
421+
return blocker.NewBlocker(blocker.BlockErr, err.Error())
422+
}
416423

417424
blockInsertQuery, blockInsertValue := bs.BlockQuery.InsertBlock(block)
418425
err = bs.QueryExecutor.ExecuteTransaction(blockInsertQuery, blockInsertValue...)

core/service/blockMainService_test.go

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,10 @@ func (*mockQueryExecutorSuccess) BeginTx() error { return nil }
335335

336336
func (*mockQueryExecutorSuccess) RollbackTx() error { return nil }
337337

338-
func (*mockQueryExecutorSuccess) ExecuteTransaction(qStr string, args ...interface{}) error {
338+
func (*mockQueryExecutorSuccess) ExecuteTransaction(string, ...interface{}) error {
339339
return nil
340340
}
341-
func (*mockQueryExecutorSuccess) ExecuteTransactions(queries [][]interface{}) error {
341+
func (*mockQueryExecutorSuccess) ExecuteTransactions([][]interface{}) error {
342342
return nil
343343
}
344344
func (*mockQueryExecutorSuccess) CommitTx() error { return nil }
@@ -577,6 +577,9 @@ func (*mockQueryExecutorSuccess) ExecuteSelect(qe string, tx bool, args ...inter
577577
mockTransaction.GetSenderAccountAddress(),
578578
mockTransaction.GetRecipientAccountAddress(),
579579
))
580+
case "SELECT sender_address, transaction_hash, transaction_bytes, status, block_height, latest " +
581+
"FROM pending_transaction WHERE block_height = ? AND status = ? AND latest = ?":
582+
mock.ExpectQuery(regexp.QuoteMeta(qe)).WillReturnRows(mock.NewRows(query.NewPendingTransactionQuery().Fields))
580583
// which is escrow expiration process
581584
default:
582585
mockRows := sqlmock.NewRows(query.NewEscrowTransactionQuery().Fields)
@@ -935,11 +938,7 @@ func (*mockPushBlockCoinbaseLotteryWinnersSuccess) CoinbaseLotteryWinners(blocks
935938
return []string{}, nil
936939
}
937940

938-
func (*mockPushBlockBlocksmithServiceSuccess) RewardBlocksmithAccountAddresses(
939-
blocksmithAccountAddresses []string,
940-
totalReward, blockTimestamp int64,
941-
height uint32,
942-
) error {
941+
func (*mockPushBlockBlocksmithServiceSuccess) RewardBlocksmithAccountAddresses([]string, int64, int64, uint32) error {
943942
return nil
944943
}
945944

@@ -1056,9 +1055,15 @@ func TestBlockService_PushBlock(t *testing.T) {
10561055
CoinbaseService: &mockPushBlockCoinbaseLotteryWinnersSuccess{},
10571056
BlocksmithService: &mockPushBlockBlocksmithServiceSuccess{},
10581057
TransactionCoreService: NewTransactionCoreService(
1058+
log.New(),
10591059
&mockQueryExecutorSuccess{},
1060+
&transaction.TypeSwitcher{
1061+
Executor: &mockQueryExecutorSuccess{},
1062+
},
1063+
&transaction.Util{},
10601064
query.NewTransactionQuery(&chaintype.MainChain{}),
10611065
query.NewEscrowTransactionQuery(),
1066+
query.NewPendingTransactionQuery(),
10621067
),
10631068
PublishedReceiptService: &mockPushBlockPublishedReceiptServiceSuccess{},
10641069
},
@@ -1116,9 +1121,13 @@ func TestBlockService_PushBlock(t *testing.T) {
11161121
CoinbaseService: &mockPushBlockCoinbaseLotteryWinnersSuccess{},
11171122
BlocksmithService: &mockPushBlockBlocksmithServiceSuccess{},
11181123
TransactionCoreService: NewTransactionCoreService(
1124+
log.New(),
11191125
&mockQueryExecutorSuccess{},
1126+
&transaction.TypeSwitcher{Executor: &mockQueryExecutorSuccess{}},
1127+
&transaction.Util{},
11201128
query.NewTransactionQuery(&chaintype.MainChain{}),
11211129
query.NewEscrowTransactionQuery(),
1130+
query.NewPendingTransactionQuery(),
11221131
),
11231132
PublishedReceiptService: &mockPushBlockPublishedReceiptServiceSuccess{},
11241133
},
@@ -1176,9 +1185,15 @@ func TestBlockService_PushBlock(t *testing.T) {
11761185
CoinbaseService: &mockPushBlockCoinbaseLotteryWinnersSuccess{},
11771186
BlocksmithService: &mockPushBlockBlocksmithServiceSuccess{},
11781187
TransactionCoreService: NewTransactionCoreService(
1188+
log.New(),
11791189
&mockQueryExecutorSuccess{},
1190+
&transaction.TypeSwitcher{
1191+
Executor: &mockQueryExecutorSuccess{},
1192+
},
1193+
&transaction.Util{},
11801194
query.NewTransactionQuery(&chaintype.MainChain{}),
11811195
query.NewEscrowTransactionQuery(),
1196+
query.NewPendingTransactionQuery(),
11821197
),
11831198
PublishedReceiptService: &mockPushBlockPublishedReceiptServiceSuccess{},
11841199
},
@@ -1236,9 +1251,15 @@ func TestBlockService_PushBlock(t *testing.T) {
12361251
CoinbaseService: &mockPushBlockCoinbaseLotteryWinnersSuccess{},
12371252
BlocksmithService: &mockPushBlockBlocksmithServiceSuccess{},
12381253
TransactionCoreService: NewTransactionCoreService(
1254+
log.New(),
12391255
&mockQueryExecutorSuccess{},
1256+
&transaction.TypeSwitcher{
1257+
Executor: &mockQueryExecutorSuccess{},
1258+
},
1259+
&transaction.Util{},
12401260
query.NewTransactionQuery(&chaintype.MainChain{}),
12411261
query.NewEscrowTransactionQuery(),
1262+
query.NewPendingTransactionQuery(),
12421263
),
12431264
PublishedReceiptService: &mockPushBlockPublishedReceiptServiceSuccess{},
12441265
},
@@ -1900,9 +1921,15 @@ func TestBlockService_AddGenesis(t *testing.T) {
19001921
BlockPoolService: &mockBlockPoolServiceNoDuplicate{},
19011922
Logger: log.New(),
19021923
TransactionCoreService: NewTransactionCoreService(
1924+
log.New(),
19031925
&mockQueryExecutorSuccess{},
1926+
&transaction.TypeSwitcher{
1927+
Executor: &mockQueryExecutorSuccess{},
1928+
},
1929+
&transaction.Util{},
19041930
query.NewTransactionQuery(&chaintype.MainChain{}),
19051931
query.NewEscrowTransactionQuery(),
1932+
query.NewPendingTransactionQuery(),
19061933
),
19071934
PublishedReceiptService: &mockAddGenesisPublishedReceiptServiceSuccess{},
19081935
},
@@ -4201,6 +4228,9 @@ func (*mockExecutorBlockPopSuccess) ExecuteSelect(qStr string, tx bool, args ...
42014228
"transaction_index FROM \"transaction\" WHERE block_id = ? ORDER BY transaction_index ASC":
42024229
mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(
42034230
sqlmock.NewRows(transactionQ.Fields))
4231+
case "SELECT sender_address, transaction_hash, transaction_bytes, status, block_height, latest FROM pending_transaction " +
4232+
"WHERE (block_height+?) = ? AND status = ? AND latest = ?":
4233+
mock.ExpectQuery(regexp.QuoteMeta(qStr)).WillReturnRows(mock.NewRows(query.NewPendingTransactionQuery().Fields))
42044234
}
42054235

42064236
return db.Query(qStr)

0 commit comments

Comments
 (0)