Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
张蕾
Geth-Modification
Commits
b7ff0d42
Commit
b7ff0d42
authored
May 25, 2017
by
Péter Szilágyi
Committed by
GitHub
May 25, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14515 from karalabe/golint-tooooolong
core: fix various golint warnings and errors
parents
07aae19e
c98bce70
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
326 additions
and
325 deletions
+326
-325
blockchain.go
core/blockchain.go
+238
-237
blocks.go
core/blocks.go
+1
-1
chain_makers.go
core/chain_makers.go
+2
-2
database_util.go
core/database_util.go
+3
-3
events.go
core/events.go
+1
-1
fees.go
core/fees.go
+1
-1
genesis.go
core/genesis.go
+1
-1
headerchain.go
core/headerchain.go
+8
-9
helper_test.go
core/helper_test.go
+6
-8
state_transition.go
core/state_transition.go
+52
-51
tx_pool.go
core/tx_pool.go
+12
-10
interpreter.go
core/vm/interpreter.go
+1
-1
No files found.
core/blockchain.go
View file @
b7ff0d42
This diff is collapsed.
Click to expand it.
core/blocks.go
View file @
b7ff0d42
...
...
@@ -18,7 +18,7 @@ package core
import
"github.com/ethereum/go-ethereum/common"
//
S
et of manually tracked bad hashes (usually hard forks)
//
BadHashes represent a s
et of manually tracked bad hashes (usually hard forks)
var
BadHashes
=
map
[
common
.
Hash
]
bool
{
common
.
HexToHash
(
"05bef30ef572270f654746da22639a7a0c97dd97a7050b9e252391996aaeb689"
)
:
true
,
common
.
HexToHash
(
"7d05d08cbc596a2e5e4f13b80a743e53e09221b5323c3a61946b20873e58583f"
)
:
true
,
...
...
core/chain_makers.go
View file @
b7ff0d42
...
...
@@ -98,10 +98,10 @@ func (b *BlockGen) Number() *big.Int {
return
new
(
big
.
Int
)
.
Set
(
b
.
header
.
Number
)
}
// AddUncheckedReceipt
s
forcefully adds a receipts to the block without a
// AddUncheckedReceipt forcefully adds a receipts to the block without a
// backing transaction.
//
// AddUncheckedReceipt
s
will cause consensus failures when used during real
// AddUncheckedReceipt will cause consensus failures when used during real
// chain processing. This is best used in conjunction with raw block insertion.
func
(
b
*
BlockGen
)
AddUncheckedReceipt
(
receipt
*
types
.
Receipt
)
{
b
.
receipts
=
append
(
b
.
receipts
,
receipt
)
...
...
core/database_util.go
View file @
b7ff0d42
...
...
@@ -64,7 +64,7 @@ var (
oldBlockReceiptsPrefix
=
[]
byte
(
"receipts-block-"
)
oldBlockHashPrefix
=
[]
byte
(
"block-hash-"
)
// [deprecated by the header/block split, remove eventually]
ChainConfigNotFoundErr
=
errors
.
New
(
"ChainConfig not found"
)
// general config not found error
ErrChainConfigNotFound
=
errors
.
New
(
"ChainConfig not found"
)
// general config not found error
mipmapBloomMu
sync
.
Mutex
// protect against race condition when updating mipmap blooms
...
...
@@ -546,7 +546,7 @@ func mipmapKey(num, level uint64) []byte {
return
append
(
mipmapPre
,
append
(
lkey
,
key
.
Bytes
()
...
)
...
)
}
// WriteM
a
pmapBloom writes each address included in the receipts' logs to the
// WriteM
i
pmapBloom writes each address included in the receipts' logs to the
// MIP bloom bin.
func
WriteMipmapBloom
(
db
ethdb
.
Database
,
number
uint64
,
receipts
types
.
Receipts
)
error
{
mipmapBloomMu
.
Lock
()
...
...
@@ -638,7 +638,7 @@ func WriteChainConfig(db ethdb.Database, hash common.Hash, cfg *params.ChainConf
func
GetChainConfig
(
db
ethdb
.
Database
,
hash
common
.
Hash
)
(
*
params
.
ChainConfig
,
error
)
{
jsonChainConfig
,
_
:=
db
.
Get
(
append
(
configPrefix
,
hash
[
:
]
...
))
if
len
(
jsonChainConfig
)
==
0
{
return
nil
,
ChainConfigNotFoundErr
return
nil
,
ErrChainConfigNotFound
}
var
config
params
.
ChainConfig
...
...
core/events.go
View file @
b7ff0d42
...
...
@@ -41,7 +41,7 @@ type NewMinedBlockEvent struct{ Block *types.Block }
// RemovedTransactionEvent is posted when a reorg happens
type
RemovedTransactionEvent
struct
{
Txs
types
.
Transactions
}
// RemovedLogEvent is posted when a reorg happens
// RemovedLog
s
Event is posted when a reorg happens
type
RemovedLogsEvent
struct
{
Logs
[]
*
types
.
Log
}
type
ChainEvent
struct
{
...
...
core/fees.go
View file @
b7ff0d42
...
...
@@ -20,4 +20,4 @@ import (
"math/big"
)
var
BlockReward
*
big
.
Int
=
big
.
NewInt
(
5e+18
)
var
BlockReward
=
big
.
NewInt
(
5e+18
)
core/genesis.go
View file @
b7ff0d42
...
...
@@ -133,7 +133,7 @@ func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig
newcfg
:=
genesis
.
configOrDefault
(
stored
)
storedcfg
,
err
:=
GetChainConfig
(
db
,
stored
)
if
err
!=
nil
{
if
err
==
ChainConfigNotFoundErr
{
if
err
==
ErrChainConfigNotFound
{
// This case happens if a genesis write was interrupted.
log
.
Warn
(
"Found genesis block without chain config"
)
err
=
WriteChainConfig
(
db
,
stored
,
newcfg
)
...
...
core/headerchain.go
View file @
b7ff0d42
...
...
@@ -201,15 +201,6 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
// header writes should be protected by the parent chain mutex individually.
type
WhCallback
func
(
*
types
.
Header
)
error
// InsertHeaderChain attempts to insert the given header chain in to the local
// chain, possibly creating a reorg. If an error is returned, it will return the
// index number of the failing header as well an error describing what went wrong.
//
// The verify parameter can be used to fine tune whether nonce verification
// should be done or not. The reason behind the optional check is because some
// of the header retrieval mechanisms already need to verfy nonces, as well as
// because nonces can be verified sparsely, not needing to check each.
func
(
hc
*
HeaderChain
)
ValidateHeaderChain
(
chain
[]
*
types
.
Header
,
checkFreq
int
)
(
int
,
error
)
{
// Do a sanity check that the provided chain is actually ordered and linked
for
i
:=
1
;
i
<
len
(
chain
);
i
++
{
...
...
@@ -257,6 +248,14 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
return
0
,
nil
}
// InsertHeaderChain attempts to insert the given header chain in to the local
// chain, possibly creating a reorg. If an error is returned, it will return the
// index number of the failing header as well an error describing what went wrong.
//
// The verify parameter can be used to fine tune whether nonce verification
// should be done or not. The reason behind the optional check is because some
// of the header retrieval mechanisms already need to verfy nonces, as well as
// because nonces can be verified sparsely, not needing to check each.
func
(
hc
*
HeaderChain
)
InsertHeaderChain
(
chain
[]
*
types
.
Header
,
writeHeader
WhCallback
,
start
time
.
Time
)
(
int
,
error
)
{
// Collect some import statistics to report on
stats
:=
struct
{
processed
,
ignored
int
}{}
...
...
core/helper_test.go
View file @
b7ff0d42
...
...
@@ -21,8 +21,6 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/core/types"
// "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
)
...
...
@@ -38,24 +36,24 @@ type TestManager struct {
Blocks
[]
*
types
.
Block
}
func
(
s
*
TestManager
)
IsListening
()
bool
{
func
(
tm
*
TestManager
)
IsListening
()
bool
{
return
false
}
func
(
s
*
TestManager
)
IsMining
()
bool
{
func
(
tm
*
TestManager
)
IsMining
()
bool
{
return
false
}
func
(
s
*
TestManager
)
PeerCount
()
int
{
func
(
tm
*
TestManager
)
PeerCount
()
int
{
return
0
}
func
(
s
*
TestManager
)
Peers
()
*
list
.
List
{
func
(
tm
*
TestManager
)
Peers
()
*
list
.
List
{
return
list
.
New
()
}
func
(
s
*
TestManager
)
BlockChain
()
*
BlockChain
{
return
s
.
blockChain
func
(
tm
*
TestManager
)
BlockChain
()
*
BlockChain
{
return
tm
.
blockChain
}
func
(
tm
*
TestManager
)
TxPool
()
*
TxPool
{
...
...
core/state_transition.go
View file @
b7ff0d42
...
...
@@ -134,112 +134,113 @@ func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, erro
return
ret
,
gasUsed
,
err
}
func
(
s
elf
*
StateTransition
)
from
()
vm
.
AccountRef
{
f
:=
s
elf
.
msg
.
From
()
if
!
s
elf
.
state
.
Exist
(
f
)
{
s
elf
.
state
.
CreateAccount
(
f
)
func
(
s
t
*
StateTransition
)
from
()
vm
.
AccountRef
{
f
:=
s
t
.
msg
.
From
()
if
!
s
t
.
state
.
Exist
(
f
)
{
s
t
.
state
.
CreateAccount
(
f
)
}
return
vm
.
AccountRef
(
f
)
}
func
(
s
elf
*
StateTransition
)
to
()
vm
.
AccountRef
{
if
s
elf
.
msg
==
nil
{
func
(
s
t
*
StateTransition
)
to
()
vm
.
AccountRef
{
if
s
t
.
msg
==
nil
{
return
vm
.
AccountRef
{}
}
to
:=
s
elf
.
msg
.
To
()
to
:=
s
t
.
msg
.
To
()
if
to
==
nil
{
return
vm
.
AccountRef
{}
// contract creation
}
reference
:=
vm
.
AccountRef
(
*
to
)
if
!
s
elf
.
state
.
Exist
(
*
to
)
{
s
elf
.
state
.
CreateAccount
(
*
to
)
if
!
s
t
.
state
.
Exist
(
*
to
)
{
s
t
.
state
.
CreateAccount
(
*
to
)
}
return
reference
}
func
(
s
elf
*
StateTransition
)
useGas
(
amount
uint64
)
error
{
if
s
elf
.
gas
<
amount
{
func
(
s
t
*
StateTransition
)
useGas
(
amount
uint64
)
error
{
if
s
t
.
gas
<
amount
{
return
vm
.
ErrOutOfGas
}
s
elf
.
gas
-=
amount
s
t
.
gas
-=
amount
return
nil
}
func
(
s
elf
*
StateTransition
)
buyGas
()
error
{
mgas
:=
s
elf
.
msg
.
Gas
()
func
(
s
t
*
StateTransition
)
buyGas
()
error
{
mgas
:=
s
t
.
msg
.
Gas
()
if
mgas
.
BitLen
()
>
64
{
return
vm
.
ErrOutOfGas
}
mgval
:=
new
(
big
.
Int
)
.
Mul
(
mgas
,
s
elf
.
gasPrice
)
mgval
:=
new
(
big
.
Int
)
.
Mul
(
mgas
,
s
t
.
gasPrice
)
var
(
state
=
s
elf
.
state
sender
=
s
elf
.
from
()
state
=
s
t
.
state
sender
=
s
t
.
from
()
)
if
state
.
GetBalance
(
sender
.
Address
())
.
Cmp
(
mgval
)
<
0
{
return
errInsufficientBalanceForGas
}
if
err
:=
s
elf
.
gp
.
SubGas
(
mgas
);
err
!=
nil
{
if
err
:=
s
t
.
gp
.
SubGas
(
mgas
);
err
!=
nil
{
return
err
}
s
elf
.
gas
+=
mgas
.
Uint64
()
s
t
.
gas
+=
mgas
.
Uint64
()
s
elf
.
initialGas
.
Set
(
mgas
)
s
t
.
initialGas
.
Set
(
mgas
)
state
.
SubBalance
(
sender
.
Address
(),
mgval
)
return
nil
}
func
(
s
elf
*
StateTransition
)
preCheck
()
error
{
msg
:=
s
elf
.
msg
sender
:=
s
elf
.
from
()
func
(
s
t
*
StateTransition
)
preCheck
()
error
{
msg
:=
s
t
.
msg
sender
:=
s
t
.
from
()
// Make sure this transaction's nonce is correct
if
msg
.
CheckNonce
()
{
if
n
:=
s
elf
.
state
.
GetNonce
(
sender
.
Address
());
n
!=
msg
.
Nonce
()
{
if
n
:=
s
t
.
state
.
GetNonce
(
sender
.
Address
());
n
!=
msg
.
Nonce
()
{
return
fmt
.
Errorf
(
"invalid nonce: have %d, expected %d"
,
msg
.
Nonce
(),
n
)
}
}
return
s
elf
.
buyGas
()
return
s
t
.
buyGas
()
}
// TransitionDb will transition the state by applying the current message and returning the result
// including the required gas for the operation as well as the used gas. It returns an error if it
// failed. An error indicates a consensus issue.
func
(
s
elf
*
StateTransition
)
TransitionDb
()
(
ret
[]
byte
,
requiredGas
,
usedGas
*
big
.
Int
,
err
error
)
{
if
err
=
s
elf
.
preCheck
();
err
!=
nil
{
func
(
s
t
*
StateTransition
)
TransitionDb
()
(
ret
[]
byte
,
requiredGas
,
usedGas
*
big
.
Int
,
err
error
)
{
if
err
=
s
t
.
preCheck
();
err
!=
nil
{
return
}
msg
:=
s
elf
.
msg
sender
:=
s
elf
.
from
()
// err checked in preCheck
msg
:=
s
t
.
msg
sender
:=
s
t
.
from
()
// err checked in preCheck
homestead
:=
s
elf
.
evm
.
ChainConfig
()
.
IsHomestead
(
self
.
evm
.
BlockNumber
)
homestead
:=
s
t
.
evm
.
ChainConfig
()
.
IsHomestead
(
st
.
evm
.
BlockNumber
)
contractCreation
:=
msg
.
To
()
==
nil
// Pay intrinsic gas
// TODO convert to uint64
intrinsicGas
:=
IntrinsicGas
(
s
elf
.
data
,
contractCreation
,
homestead
)
intrinsicGas
:=
IntrinsicGas
(
s
t
.
data
,
contractCreation
,
homestead
)
if
intrinsicGas
.
BitLen
()
>
64
{
return
nil
,
nil
,
nil
,
vm
.
ErrOutOfGas
}
if
err
=
s
elf
.
useGas
(
intrinsicGas
.
Uint64
());
err
!=
nil
{
if
err
=
s
t
.
useGas
(
intrinsicGas
.
Uint64
());
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
var
(
evm
=
s
elf
.
evm
evm
=
s
t
.
evm
// vm errors do not effect consensus and are therefor
// not assigned to err, except for insufficient balance
// error.
vmerr
error
)
if
contractCreation
{
ret
,
_
,
s
elf
.
gas
,
vmerr
=
evm
.
Create
(
sender
,
self
.
data
,
self
.
gas
,
self
.
value
)
ret
,
_
,
s
t
.
gas
,
vmerr
=
evm
.
Create
(
sender
,
st
.
data
,
st
.
gas
,
st
.
value
)
}
else
{
// Increment the nonce for the next transaction
s
elf
.
state
.
SetNonce
(
sender
.
Address
(),
self
.
state
.
GetNonce
(
sender
.
Address
())
+
1
)
ret
,
s
elf
.
gas
,
vmerr
=
evm
.
Call
(
sender
,
self
.
to
()
.
Address
(),
self
.
data
,
self
.
gas
,
self
.
value
)
s
t
.
state
.
SetNonce
(
sender
.
Address
(),
st
.
state
.
GetNonce
(
sender
.
Address
())
+
1
)
ret
,
s
t
.
gas
,
vmerr
=
evm
.
Call
(
sender
,
st
.
to
()
.
Address
(),
st
.
data
,
st
.
gas
,
st
.
value
)
}
if
vmerr
!=
nil
{
log
.
Debug
(
"VM returned with error"
,
"err"
,
err
)
...
...
@@ -250,33 +251,33 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
return
nil
,
nil
,
nil
,
vmerr
}
}
requiredGas
=
new
(
big
.
Int
)
.
Set
(
s
elf
.
gasUsed
())
requiredGas
=
new
(
big
.
Int
)
.
Set
(
s
t
.
gasUsed
())
s
elf
.
refundGas
()
s
elf
.
state
.
AddBalance
(
self
.
evm
.
Coinbase
,
new
(
big
.
Int
)
.
Mul
(
self
.
gasUsed
(),
self
.
gasPrice
))
s
t
.
refundGas
()
s
t
.
state
.
AddBalance
(
st
.
evm
.
Coinbase
,
new
(
big
.
Int
)
.
Mul
(
st
.
gasUsed
(),
st
.
gasPrice
))
return
ret
,
requiredGas
,
s
elf
.
gasUsed
(),
err
return
ret
,
requiredGas
,
s
t
.
gasUsed
(),
err
}
func
(
s
elf
*
StateTransition
)
refundGas
()
{
func
(
s
t
*
StateTransition
)
refundGas
()
{
// Return eth for remaining gas to the sender account,
// exchanged at the original rate.
sender
:=
s
elf
.
from
()
// err already checked
remaining
:=
new
(
big
.
Int
)
.
Mul
(
new
(
big
.
Int
)
.
SetUint64
(
s
elf
.
gas
),
self
.
gasPrice
)
s
elf
.
state
.
AddBalance
(
sender
.
Address
(),
remaining
)
sender
:=
s
t
.
from
()
// err already checked
remaining
:=
new
(
big
.
Int
)
.
Mul
(
new
(
big
.
Int
)
.
SetUint64
(
s
t
.
gas
),
st
.
gasPrice
)
s
t
.
state
.
AddBalance
(
sender
.
Address
(),
remaining
)
// Apply refund counter, capped to half of the used gas.
uhalf
:=
remaining
.
Div
(
s
elf
.
gasUsed
(),
common
.
Big2
)
refund
:=
math
.
BigMin
(
uhalf
,
s
elf
.
state
.
GetRefund
())
s
elf
.
gas
+=
refund
.
Uint64
()
uhalf
:=
remaining
.
Div
(
s
t
.
gasUsed
(),
common
.
Big2
)
refund
:=
math
.
BigMin
(
uhalf
,
s
t
.
state
.
GetRefund
())
s
t
.
gas
+=
refund
.
Uint64
()
s
elf
.
state
.
AddBalance
(
sender
.
Address
(),
refund
.
Mul
(
refund
,
self
.
gasPrice
))
s
t
.
state
.
AddBalance
(
sender
.
Address
(),
refund
.
Mul
(
refund
,
st
.
gasPrice
))
// Also return remaining gas to the block gas counter so it is
// available for the next transaction.
s
elf
.
gp
.
AddGas
(
new
(
big
.
Int
)
.
SetUint64
(
self
.
gas
))
s
t
.
gp
.
AddGas
(
new
(
big
.
Int
)
.
SetUint64
(
st
.
gas
))
}
func
(
s
elf
*
StateTransition
)
gasUsed
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Sub
(
s
elf
.
initialGas
,
new
(
big
.
Int
)
.
SetUint64
(
self
.
gas
))
func
(
s
t
*
StateTransition
)
gasUsed
()
*
big
.
Int
{
return
new
(
big
.
Int
)
.
Sub
(
s
t
.
initialGas
,
new
(
big
.
Int
)
.
SetUint64
(
st
.
gas
))
}
core/tx_pool.go
View file @
b7ff0d42
...
...
@@ -209,6 +209,7 @@ func (pool *TxPool) resetState() {
pool
.
promoteExecutables
(
currentState
)
}
// Stop terminates the transaction pool.
func
(
pool
*
TxPool
)
Stop
()
{
pool
.
events
.
Unsubscribe
()
close
(
pool
.
quit
)
...
...
@@ -238,6 +239,7 @@ func (pool *TxPool) SetGasPrice(price *big.Int) {
log
.
Info
(
"Transaction pool price threshold updated"
,
"price"
,
price
)
}
// State returns the virtual managed state of the transaction pool.
func
(
pool
*
TxPool
)
State
()
*
state
.
ManagedState
{
pool
.
mu
.
RLock
()
defer
pool
.
mu
.
RUnlock
()
...
...
@@ -850,22 +852,22 @@ func newTxSet() *txSet {
// contains returns true if the set contains the given transaction hash
// (not thread safe, should be called from a locked environment)
func
(
self
*
txSet
)
contains
(
hash
common
.
Hash
)
bool
{
_
,
ok
:=
self
.
txMap
[
hash
]
func
(
ts
*
txSet
)
contains
(
hash
common
.
Hash
)
bool
{
_
,
ok
:=
ts
.
txMap
[
hash
]
return
ok
}
// add adds a transaction hash to the set, then removes entries older than txSetDuration
// (not thread safe, should be called from a locked environment)
func
(
self
*
txSet
)
add
(
hash
common
.
Hash
)
{
self
.
txMap
[
hash
]
=
struct
{}{}
func
(
ts
*
txSet
)
add
(
hash
common
.
Hash
)
{
ts
.
txMap
[
hash
]
=
struct
{}{}
now
:=
time
.
Now
()
self
.
txOrd
[
self
.
addPtr
]
=
txOrdType
{
hash
:
hash
,
time
:
now
}
self
.
addPtr
++
ts
.
txOrd
[
ts
.
addPtr
]
=
txOrdType
{
hash
:
hash
,
time
:
now
}
ts
.
addPtr
++
delBefore
:=
now
.
Add
(
-
txSetDuration
)
for
self
.
delPtr
<
self
.
addPtr
&&
self
.
txOrd
[
self
.
delPtr
]
.
time
.
Before
(
delBefore
)
{
delete
(
self
.
txMap
,
self
.
txOrd
[
self
.
delPtr
]
.
hash
)
delete
(
self
.
txOrd
,
self
.
delPtr
)
self
.
delPtr
++
for
ts
.
delPtr
<
ts
.
addPtr
&&
ts
.
txOrd
[
ts
.
delPtr
]
.
time
.
Before
(
delBefore
)
{
delete
(
ts
.
txMap
,
ts
.
txOrd
[
ts
.
delPtr
]
.
hash
)
delete
(
ts
.
txOrd
,
ts
.
delPtr
)
ts
.
delPtr
++
}
}
core/vm/interpreter.go
View file @
b7ff0d42
...
...
@@ -91,7 +91,7 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack
}
// Run loops and evaluates the contract's code with the given input data and returns
// the return byte-slice and an error if one occured.
// the return byte-slice and an error if one occur
r
ed.
//
// It's important to note that any errors returned by the interpreter should be
// considered a revert-and-consume-all-gas operation. No error specific checks
...
...
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